home *** CD-ROM | disk | FTP | other *** search
- /*
- File: FWCCMDriver.c
-
- Contains: Driver software for CCM cameras implemented as a video
- digitizer component.
-
- Written by: Erik Staats
-
- Copyright: © 1996-1997 by Apple Computer, Inc., all rights reserved.
-
- Change History (most recent first):
-
- <FW33> 8/15/97 EA Changed to skip frames when CPU is saturated.
- <FW32> 6/5/97 EA Unified the three DCL programs into one, with variable
- callProcs. Unified the three colorspace conversion routines,
- then made the result modular by target depth. Changed DCL design
- to use hardware to skip frames we can't accept, to eliminate
- fruitless callProcs, eliminate most mangled frames, and support
- Pele (where we don't see sync in running DMA). Considerably
- improved record (async grab) performance in some cases.
- <FW31> 3/18/97 ES Changed driver description version to final.
- <FW31> 3/18/97 ES Changed driver description version to final.
- <FW30> 2/20/97 ES Changed to use plug in dispatch table.
- <FW29> 1/16/97 ES Added use of DCLUpdateList commands.
- <FW28> 12/27/96 ES Changed FWCCMOpen to set csrRegBaseEntryID invalid at the
- beginning.
- <FW27> 12/27/96 ES Changed a bunch of "FWDriver"s to "FWClient"s.
- <FW26> 12/22/96 ES Changed IsochPortAction to IsochPortControl.
- <FW25> 12/10/96 ES Removed early reset notification and added isoch channel
- forceful stop notification.
- <FW24> 12/4/96 ES Fixed crashing bug when isochronous resources cannot be
- allocated.
- <FW23> 10/24/96 ES Changed to work with Component Driver expert.
- <FW22> 10/16/96 ES Added bus management notification proc to improve hot
- plugability.
- <FW21> 9/27/96 ES Changed to use set driver interface calls rather than driver
- interface table.
- <FW20> 9/26/96 ES Fixed problem with timeout in FWCCMGrabOneFrame.
- <FW19> 9/16/96 ES Changed FireWire driver interface procs to return command
- acceptance.
- <FW18> 9/4/96 ES Added more deallocation.
- <FW17> 9/3/96 ES Added reset notification handling. Will restart active
- isochronous channel on resets.
- <FW16> 8/29/96 ES Changed FWRegisterDriver to take driver interface proc table.
- <FW15> 8/28/96 ES Changed the way trial works in InitIsochPort and fixed setting
- of isoch channel number in camera.
- <FW14> 8/26/96 ES Changed to new command object interface.
- <FW13> 8/26/96 ES Changed some constant names.
- <FW12> 8/16/96 ES Changed FWAllocateLocalIsochronousPort to take param block. Made
- some other minor modifications.
- <FW11> 8/15/96 ES Updated for changes to isochronous mechanisms.
- <FW10> 8/2/96 ES Updated for more isochronous changes.
- <FW9> 8/2/96 ES Updated to work with QuickTimeComponents.h from ETO #21.
- <FW8> 8/1/96 ES Took out unused local variables.
- <FW7> 7/31/96 ES Changed to use new isochronous buffer architecture.
- <FW6> 7/8/96 ES Changed call to FWAllocateIsochronousChannelID to set IRM
- allocation to true.
- <FW5> 6/28/96 ES Changed to use DebugStrStatus instead of DebugStr.
- <FW4> 6/27/96 ES Took out include of AdminMessagePort.h.
- <FW3> 6/20/96 ES Changed so we can build with MrC.
- <FW2> 6/20/96 ES Filled in contains and written by fields.
- <FW1> 6/20/96 ES first checked in
-
- */
-
- #include <Types.h>
- #include <Errors.h>
- #include <Devices.h>
- #include <MixedMode.h>
- #include <DriverServices.h>
- #include <FireWire.h>
- #include <Components.h>
- #include <QuickTimeComponents.h>
- #include <FWCCMDriver.h>
- /*zzz*/
- #include <stdio.h>
- char debugStr[256];
- /*zzz*/
- //zzz Use descriptions out of documentation for standard vdig procs comments.
- //zzz need some register defs.
-
-
- //////////////////////////////////////////////////////////////////////////////
- //
- // ## Some items not currently implemented ##
- //
- // We could use more optimized aligned (and double) writes in some cases
- // during the colorspace conversion.
- //
- // We could use a higher-quality colorspace conversion.
- //
- // We could support the 640x480 4:1:1 YUV mode (200 mbps required).
- //
- // We could display blue when there is no signal, using timeouts.
- //
- // It would be nice during playthrough to sync with the vertical refresh
- // in order to avoid tearing the image.
- //
- // Could add a non-optimized colorspace conversion routine that handles all
- // frame rates. The lower frame rates are sometimes helpful in debugging.
- //
- //////////////////////////////////////////////////////////////////////////////
-
-
- /*zzz should be in a system header file*/
- enum
- {
- kComponentDriverPluginVersion = 0x00010000
- };
-
- typedef pascal ComponentResult (ComponentDriverInitializeProc) (
- RegEntryIDPtr pRegEntryID);
- typedef ComponentDriverInitializeProc
- *ComponentDriverInitializeProcPtr;
-
- typedef pascal ComponentResult (ComponentDriverFinalizeProc) (
- RegEntryIDPtr pRegEntryID);
- typedef ComponentDriverFinalizeProc
- *ComponentDriverFinalizeProcPtr;
-
- struct ComponentDriverPluginDispatchTableStruct
- {
- UInt32 pluginVersion;
- ComponentDriverInitializeProcPtr componentDriverInitializeProc; // Proc that initializes the component driver.
- ComponentDriverFinalizeProcPtr componentDriverFinalizeProc; // Proc that finalizes the component driver.
- ComponentRoutineProcPtr componentInterfaceProcPtr; // Proc that polls for interrupts.
- };
- typedef struct ComponentDriverPluginDispatchTableStruct
- ComponentDriverPluginDispatchTable,
- *ComponentDriverPluginDispatchTablePtr;
- /*zzz*/
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Internal procedure prototypes.
- //
-
- static OSStatus FWCCMBusManagementNotify (
- FWClientInterfaceParamsPtr pFWClientInterfaceParams,
- UInt32 *pCommandAcceptance);
-
- static void FWResetNotifyRestartChannelCompletionProc1 (
- FWCommandObjectID fwCommandObjectID,
- OSStatus commandStatus,
- UInt32 completionProcData);
-
- static void FWResetNotifyRestartChannelCompletionProc2 (
- FWCommandObjectID fwCommandObjectID,
- OSStatus commandStatus,
- UInt32 completionProcData);
-
- static OSStatus FWCCMInitIsochPort (
- FWClientInitIsochPortParamsPtr
- pInitIsochPortParams,
- UInt32 *pCommandAcceptance);
-
- static OSStatus FWCCMReleaseIsochPort (
- FWClientReleaseIsochPortParamsPtr
- pReleaseIsochPortParams,
- UInt32 *pCommandAcceptance);
-
- static OSStatus FWCCMStartIsochPort (
- FWClientIsochPortControlParamsPtr
- pIsochPortControlParams,
- UInt32 *pCommandAcceptance);
-
- static OSStatus FWCCMStopIsochPort (
- FWClientIsochPortControlParamsPtr
- pIsochPortControlParams,
- UInt32 *pCommandAcceptance);
-
- static OSStatus FWCCMIsochChannelForceStopNotification (
- IsochChannelID isochChannelID,
- UInt32 stopCondition);
-
- pascal ComponentResult ComponentInterface (
- ComponentParameters *pComponentParams,
- Handle componentSpecificData);
-
- static pascal ComponentResult FWCCMOpen (
- Handle componentSpecificData,
- ComponentOpenParamsPtr pComponentOpenParams);
-
- static void FWCCMWriteDCLProgram(
- FWCCMVDigDataPtr pFWCCMVDigData);
-
- static void FWCCMSetupDCLProgram(
- FWCCMVDigDataPtr pFWCCMVDigData,
- DCLCallCommandProcPtr callProc);
-
- static void FWCCMSetDCLProgramEndFrame(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 endFrameNum);
-
- static pascal ComponentResult FWCCMClose (
- Handle componentSpecificData,
- ComponentCloseParamsPtr pComponentCloseParams);
-
- static pascal ComponentResult FWCCMVersion (
- Handle componentSpecificData);
-
- static pascal ComponentResult FWCCMInitializeDriver (
- RegEntryIDPtr pRegEntryID);
-
- static pascal ComponentResult FWCCMFinalizeDriver (
- RegEntryIDPtr pRegEntryID);
-
- static pascal VideoDigitizerError FWCCMGetActiveSrcRect (
- Handle componentSpecificData,
- VDigGetActiveSrcRectParamsPtr
- pVDigGetActiveSrcRectParams);
-
- static pascal VideoDigitizerError FWCCMSetDigitizerRect (
- Handle componentSpecificData,
- VDigSetDigitizerRectParamsPtr
- pVDigSetDigitizerRectParams);
-
- static pascal VideoDigitizerError FWCCMGetDigitizerInfo (
- Handle componentSpecificData,
- VDigGetDigitizerInfoParamsPtr
- pVDigGetDigitizerInfoParams);
-
- static pascal VideoDigitizerError FWCCMGetCurrentFlags (
- Handle componentSpecificData,
- VDigGetCurrentFlagsParamsPtr
- pVDigGetCurrentFlagsParams);
-
- static pascal VideoDigitizerError FWCCMSetPlayThruDestination (
- Handle componentSpecificData,
- VDigSetPlayThruDestinationParamsPtr
- pVDigSetPlayThruDestinationParams);
-
- static pascal VideoDigitizerError FWCCMSetPlayThruOnOff (
- Handle componentSpecificData,
- VDigSetPlayThruOnOffParamsPtr
- pVDigSetPlayThruOnOffParams);
-
- static pascal VideoDigitizerError FWCCMSetHue (
- Handle componentSpecificData,
- VDigSetHueParamsPtr pVDigSetHueParams);
-
- static pascal VideoDigitizerError FWCCMSetSaturation (
- Handle componentSpecificData,
- VDigSetSaturationParamsPtr pVDigSetSaturationParams);
-
- static pascal VideoDigitizerError FWCCMGetHue (
- Handle componentSpecificData,
- VDigGetHueParamsPtr pVDigGetHueParams);
-
- static pascal VideoDigitizerError FWCCMGetSaturation (
- Handle componentSpecificData,
- VDigGetSaturationParamsPtr pVDigGetSaturationParams);
-
- static pascal VideoDigitizerError FWCCMGrabOneFrame (
- Handle componentSpecificData);
-
- static pascal VideoDigitizerError FWCCMPreflightDestination (
- Handle componentSpecificData,
- VDigPreflightDestinationParamsPtr
- pVDigPreflightDestinationParams);
-
- static pascal VideoDigitizerError FWCCMSetBlackLevelValue (
- Handle componentSpecificData,
- VDigSetBlackLevelValueParamsPtr
- pVDigSetBlackLevelValueParams);
-
- static pascal VideoDigitizerError FWCCMGetBlackLevelValue (
- Handle componentSpecificData,
- VDigGetBlackLevelValueParamsPtr
- pVdigGetBlackLevelValueParams);
-
- static pascal VideoDigitizerError FWCCMSetWhiteLevelValue (
- Handle componentSpecificData,
- VDigSetWhiteLevelValueParamsPtr
- pVDigSetWhiteLevelValueParams);
-
- static pascal VideoDigitizerError FWCCMGetWhiteLevelValue (
- Handle componentSpecificData,
- VDigGetWhiteLevelValueParamsPtr
- pVDigGetWhiteLevelValueParams);
-
- static pascal VideoDigitizerError FWCCMGetNumberOfInputs (
- Handle componentSpecificData,
- VDigGetNumberOfInputsParamsPtr
- pVDigGetNumberOfInputsParams);
-
- static pascal VideoDigitizerError FWCCMGetInput (
- Handle componentSpecificData,
- VDigGetInputParamsPtr pVDigGetInputParams);
-
- static pascal VideoDigitizerError FWCCMSetInputStandard (
- Handle componentSpecificData,
- VDigSetInputStandardParamsPtr
- pVDigSetInputStandardParams);
-
- static pascal VideoDigitizerError FWCCMSetupBuffers (
- Handle componentSpecificData,
- VDigSetupBuffersParamsPtr pVDigSetupBuffersParams);
-
- static pascal VideoDigitizerError FWCCMGrabOneFrameAsync (
- Handle componentSpecificData,
- VDigGrabOneFrameAsyncParamsPtr
- pVDigGrabOneFrameAsyncParams);
-
- static pascal long FWCCMDone (
- Handle componentSpecificData,
- VDigDoneParamsPtr pVDigDoneParams);
-
- static pascal VideoDigitizerError FWCCMSetFrameRate (
- Handle componentSpecificData,
- VDigSetFrameRateParamsPtr pVDigSetFrameRateParams);
-
- static pascal VideoDigitizerError FWCCMReleaseAsyncBuffers (
- Handle componentSpecificData);
-
- static void FWCCMCopyToDestPixMap (
- FWCCMVDigDataPtr pFWCCMVDigData);
-
- static void FWCCMAsyncGrabIsochHandler (
- DCLCommandPtr pDCLCommandPtr);
-
- static void FWCCMCopyIsochChannelToVdigBuffer (
- FWCCMVDigDataPtr pFWCCMVDigData,
- DCLTransferPacketPtr pDCLTransferPacket,
- VdigBufferRecQElemPtr pVdigBufferRecQElem);
-
- static void FWCCMPlayThruIsochHandler (
- DCLCommandPtr pDCLCommandPtr);
-
- static void FWCCMGrabOneFrameIsochHandler (
- DCLCommandPtr pDCLCommandPtr);
-
- static void FWCCMCopyIsochChannelToDestPixMap (
- FWCCMVDigDataPtr pFWCCMVDigData,
- DCLTransferPacketPtr pDCLTransferPacket);
-
- static void FWCCMConvertYUV422ToRGB16(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 *pSrcYUV,
- UInt32 byteCountYUV,
- UInt32 *pDstRGB,
- UInt32 rowBytesRGB);
-
- static void FWCCMConvertYUV422ToRGB16Double(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 *pSrcYUV,
- UInt32 byteCountYUV,
- UInt32 *pDstRGB,
- UInt32 rowBytesRGB);
-
- static void FWCCMConvertYUV422ToRGB32(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 *pSrcYUV,
- UInt32 byteCountYUV,
- UInt32 *pDstRGB,
- UInt32 rowBytesRGB);
-
- static void FWCCMConvertYUV422ToRGB32Double(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 *pSrcYUV,
- UInt32 byteCountYUV,
- UInt32 *pDstRGB,
- UInt32 rowBytesRGB);
-
- static void FWCCMDelayForHardware (
- Duration duration);
-
- static void FWCCMClientCommandCompletionProc (
- FWCommandObjectID fwCommandObjectID,
- OSStatus commandStatus,
- UInt32 completionProcData);
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // The driver descriptor.
- //
-
- DriverDescription TheDriverDescription =
- {
- kTheDescriptionSignature,
- kInitialDriverDescriptor,
- {
- "\pfwa02d,100",
- 1, 0, finalStage, 1,
- },
- {
- kDriverIsUnderExpertControl,
- "\pFWCCMDriver",
- },
-
- 1,
- 'comp',
- 'vdig',
- 1,0,0,0
- };
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // The plug in dispatch table.
- //
-
- ComponentDriverPluginDispatchTable
- ThePluginDispatchTable =
- {
- kComponentDriverPluginVersion,
- FWCCMInitializeDriver,
- FWCCMFinalizeDriver,
- ComponentInterface
- };
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // Global driver data.
- //
-
- FWCCMDriverDataPtr gpFWCCMDriverData = nil;
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMTerminate
- //
- // This proc terminates the FireWire CCM driver.
- //
-
- long FWCCMTerminate()
- {
- OSStatus status = noErr;
-
- // Dispose of FWCCM data.
- if (gpFWCCMDriverData != nil)
- {
- PoolDeallocate ((Ptr) gpFWCCMDriverData);
- gpFWCCMDriverData = nil;
- }
-
- return status;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMBusManagementNotify
- //
- // This routine handles reset notification when bus management has been
- // established. If ISO_EN is set before the cycle master is enabled, ISO_EN
- // will get cleared with the cycle master begins sending cycle start packets.
- // Thus, we need this routine to execute after the bus manager has enabled
- // the cycle master.
- //zzz this routine should check if ISO_EN has been cleared before doing
- //zzz anything.
- //zzz maybe this routine just needs to set ISO_EN instead of doing a full
- //zzz stop and start.
- //
-
- static OSStatus FWCCMBusManagementNotify(
- FWClientInterfaceParamsPtr pFWClientInterfaceParams,
- UInt32 *pCommandAcceptance)
- {
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCommandObjectID isochChannelCommandObjectID;
- OSStatus status = noErr;
-
- // Get our driver data.
- pFWCCMDriverData = (FWCCMDriverDataPtr) pFWClientInterfaceParams->fwClientSpecificData;
- pFWCCMVDigData = pFWCCMDriverData->pFWCCMVDigData;
-
- // Restart isochronous channel if it should be active.
- if ((pFWCCMVDigData->channelActive) &&
- (!(pFWCCMVDigData->startStopIsochChannelCommandObjectsInUse)))
- {
- // Command objects now in use.
- pFWCCMVDigData->startStopIsochChannelCommandObjectsInUse = true;
-
- // Stop channel.
- isochChannelCommandObjectID = pFWCCMVDigData->stopIsochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- 0,
- FWResetNotifyRestartChannelCompletionProc1,
- (UInt32) pFWCCMVDigData);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
- pFWCCMVDigData->channelActive = false;
- FWStopIsochronousChannel (isochChannelCommandObjectID);
- }
-
- // Complete FireWire client command.
- FWClientCommandIsComplete (pFWClientInterfaceParams->fwClientCommandID, status);
-
- // Return command acceptance.
- //zzz is this the right way? If we've completed the command, we can accept more.
- *pCommandAcceptance = kFWClientCommandAcceptNoMore;
-
- return status;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWResetNotifyRestartChannelCompletionProc1
- //
- // This routine will issue a start isoch channel command after a stop isoch
- // channel command has completed.
- //
-
- static void FWResetNotifyRestartChannelCompletionProc1(
- FWCommandObjectID fwCommandObjectID,
- OSStatus commandStatus,
- UInt32 completionProcData)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCommandObjectID isochChannelCommandObjectID;
-
- // Get VDig data from completionProcData.
- pFWCCMVDigData = (FWCCMVDigDataPtr) completionProcData;
-
- // Start channel.
- isochChannelCommandObjectID = pFWCCMVDigData->startIsochChannelCommandObjectID;
- FWSetFWCommandParams
- (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- 0,
- FWResetNotifyRestartChannelCompletionProc2,
- (UInt32) &(pFWCCMVDigData->startStopIsochChannelCommandObjectsInUse));
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
- pFWCCMVDigData->channelActive = true;
- FWStartIsochronousChannel (isochChannelCommandObjectID);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWResetNotifyRestartChannelCompletionProc2
- //
- // This routine will release a lock on the start and stop isoch channel
- // command object. A pointer to the lock is provided in the completionProcData.
- //
-
- static void FWResetNotifyRestartChannelCompletionProc2(
- FWCommandObjectID fwCommandObjectID,
- OSStatus commandStatus,
- UInt32 completionProcData)
- {
- UInt32 *pStartStopIsochChannelCommandObjectsInUse;
-
- // Clear lock on start/stop command objects.
- pStartStopIsochChannelCommandObjectsInUse = (UInt32 *) completionProcData;
- *pStartStopIsochChannelCommandObjectsInUse = false;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMInitIsochPort
- //
- // This routine initializes an isochronous port for the FireWire CCM camera.
- // If the request is for the talking port, this routine sets up the camera's
- // isochronous port. If the request is for the listening port, this routine
- // sets up the local node's isochronous port.
- //zzz should have resolution/frame-rate in ref con and program it
- //
-
- static OSStatus FWCCMInitIsochPort(
- FWClientInitIsochPortParamsPtr
- pInitIsochPortParams,
- UInt32 *pCommandAcceptance)
- {
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCommandObjectID isochPortCommandObjectID;
- FWCommandObjectID asynchCommandObjectID;
- UInt32 channelNum;
- UInt32 speed;
- Boolean portIsTalker;
- Boolean trial;
- UInt32 fwCCMReg;
- OSStatus status = noErr;
-
- // DebugStr ((ConstStr255Param) "\pFWCCMInitIsochPort");
-
- // Get our driver data.
- pFWCCMDriverData = (FWCCMDriverDataPtr)
- pInitIsochPortParams->fwClientInterfaceParams.fwClientSpecificData;
-
- // Get our VDig data from refCon.
- pFWCCMVDigData = (FWCCMVDigDataPtr) pInitIsochPortParams->fwClientIsochPortParams.refCon;
-
- // Get speed and channel number.
- speed = pInitIsochPortParams->speed;
- channelNum = pInitIsochPortParams->channelNum;
-
- // Is this request for the talking port?
- portIsTalker = pInitIsochPortParams->fwClientIsochPortParams.portIsTalker;
-
- // Is this a trial?
- trial = pInitIsochPortParams->trial;
-
- // Initialize.
- if (portIsTalker)
- {
- // Port is for camera.
- if (!trial)
- {
- // Check params.
- if ((speed > kFWSpeed100MBit) || (channelNum > 15))
- status = paramErr;
-
- // Program camera for given channel number.
- if (status == noErr)
- {
- fwCCMReg = channelNum << 28;
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x060C,
- (Ptr) &fwCCMReg,
- 4);
-
- FWCCMDelayForHardware (100*durationMillisecond);
- status = FWWrite (asynchCommandObjectID);
- }
- }
- else
- {
- // Return supported channel numbers.
- pInitIsochPortParams->supportedChannelNumHi = 0xFFFF0000;
- pInitIsochPortParams->supportedChannelNumLo = 0x00000000;
-
- // Return supported speed.
- if (speed > kFWSpeed100MBit)
- pInitIsochPortParams->speed = kFWSpeed100MBit;
- }
- }
- else
- {
- // Port is for local node.
- if (!trial)
- {
- // Allocate an isoch port ID.
- status = FWAllocateIsochPortID (&(pFWCCMVDigData->isochPortID),
- pFWCCMVDigData->dclProgramID,
- channelNum,
- speed,
- portIsTalker);
-
- // Send an allocate isoch port command to allocate port for listening.
- if (status == noErr)
- {
- // Set up command object.
- isochPortCommandObjectID = pFWCCMVDigData->isochPortCommandObjectID;
- FWSetFWCommandParams (isochPortCommandObjectID,
- (FWReferenceID) pFWCCMDriverData->fwDriverID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochPortCommandIsochPortID (isochPortCommandObjectID,
- pFWCCMVDigData->isochPortID);
-
- // Send command
- status = FWAllocateLocalIsochronousPort (isochPortCommandObjectID);
- }
- }
- else
- {
- // Return supported channel numbers.
- pInitIsochPortParams->supportedChannelNumHi = 0xFFFF0000;
- pInitIsochPortParams->supportedChannelNumLo = 0x00000000;
-
- // Return supported speed.
- if (speed > kFWSpeed100MBit)
- pInitIsochPortParams->speed = kFWSpeed100MBit;
- }
- }
-
- // Complete FireWire client command.
- FWClientCommandIsComplete
- (pInitIsochPortParams->fwClientInterfaceParams.fwClientCommandID, status);
-
- // Return command acceptance.
- //zzz is this the right way? If we've completed the command, we can accept more.
- *pCommandAcceptance = kFWClientCommandAcceptNoMore;
-
- return status;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMReleaseIsochPort
- //
- // This procedure releases resources allocated for the isochronous channel.
- // If the channel is a listener, this routine will release the local
- // isochronous port.
- //
-
- static OSStatus FWCCMReleaseIsochPort(
- FWClientReleaseIsochPortParamsPtr
- pReleaseIsochPortParams,
- UInt32 *pCommandAcceptance)
- {
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCommandObjectID isochPortCommandObjectID;
- Boolean portIsTalker;
- OSStatus status = noErr;
-
- // DebugStr ((ConstStr255Param) "\pFWCCMReleaseIsochPort");
-
- // Get our driver data.
- pFWCCMDriverData = (FWCCMDriverDataPtr)
- pReleaseIsochPortParams->fwClientInterfaceParams.fwClientSpecificData;
-
- // Get our VDig data from refCon.
- pFWCCMVDigData = (FWCCMVDigDataPtr)
- pReleaseIsochPortParams->fwClientIsochPortParams.refCon;
-
- // Is this request for the talking port?
- portIsTalker = pReleaseIsochPortParams->fwClientIsochPortParams.portIsTalker;
-
- if (!portIsTalker)
- {
- // Set up command object to release port.
- isochPortCommandObjectID = pFWCCMVDigData->isochPortCommandObjectID;
- FWSetFWCommandParams (isochPortCommandObjectID,
- (FWReferenceID) pFWCCMDriverData->fwDriverID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochPortCommandIsochPortID
- (isochPortCommandObjectID, pFWCCMVDigData->isochPortID);
-
- FWReleaseLocalIsochronousPort (isochPortCommandObjectID);
-
- // Deallocate isoch port ID.
- FWDeallocateIsochPortID (pFWCCMVDigData->isochPortID);
- }
-
- // Complete FireWire client command.
- FWClientCommandIsComplete
- (pReleaseIsochPortParams->fwClientInterfaceParams.fwClientCommandID, status);
-
- // Return command acceptance.
- //zzz is this the right way? If we've completed the command, we can accept more.
- *pCommandAcceptance = kFWClientCommandAcceptNoMore;
-
- return status;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMStartIsochPort
- //
- // This procedure starts the isochronous channel. If the channel is a
- // talker, this procedure will program the camera to start sending isochronous
- // data. If the channel is a listener, this procedure will start the local
- // isochronous port.
- //
-
- static OSStatus FWCCMStartIsochPort(
- FWClientIsochPortControlParamsPtr
- pIsochPortControlParams,
- UInt32 *pCommandAcceptance)
- {
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCommandObjectID asynchCommandObjectID;
- FWCommandObjectID isochPortCommandObjectID;
- Boolean portIsTalker;
- UInt32 *pFWCCMReg;
- OSStatus status = noErr;
-
- // DebugStr ((ConstStr255Param) "\pFWCCMStartIsochPort");
-
- // Get our driver data.
- pFWCCMDriverData = (FWCCMDriverDataPtr)
- pIsochPortControlParams->fwClientInterfaceParams.fwClientSpecificData;
-
- // Get our VDig data from refCon.
- pFWCCMVDigData = (FWCCMVDigDataPtr) pIsochPortControlParams->fwClientIsochPortParams.refCon;
-
- // Is this request for the talking port?
- portIsTalker = pIsochPortControlParams->fwClientIsochPortParams.portIsTalker;
-
- if (portIsTalker)
- {
- // Send an async write packet to ISO_EN register.
- pFWCCMReg = &(pFWCCMVDigData->fwCCMReg);
- *pFWCCMReg = 0x80000000;
- asynchCommandObjectID = pFWCCMVDigData->startAsynchCommandObjectID;
- FWSetFWCommandCompletionProcData
- (asynchCommandObjectID,
- (UInt32) pIsochPortControlParams->fwClientInterfaceParams.fwClientCommandID);
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0614,
- (Ptr) pFWCCMReg,
- 4);
-
- // Write register.
- FWCCMDelayForHardware (100*durationMillisecond);
- status = FWWrite (asynchCommandObjectID);
- }
- else
- {
- // Set up command object to start port.
- isochPortCommandObjectID = pFWCCMVDigData->isochPortCommandObjectID;
- FWSetFWCommandParams
- (isochPortCommandObjectID,
- (FWReferenceID) pFWCCMDriverData->fwDriverID,
- 0,
- FWCCMClientCommandCompletionProc,
- (UInt32) pIsochPortControlParams->fwClientInterfaceParams.fwClientCommandID);
- FWSetIsochPortCommandIsochPortID (isochPortCommandObjectID,
- pFWCCMVDigData->isochPortID);
-
- // Send command to start port.
- status = FWStartLocalIsochronousPort (isochPortCommandObjectID);
- }
-
- // Return command acceptance.
- //zzz is this the right way? If we've completed the command, we can accept more.
- *pCommandAcceptance = kFWClientCommandAcceptNoMore;
-
- return status;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMStopIsochPort
- //
- // This procedure stops the isochronous channel. If the channel is a
- // talker, this procedure will program the camera to stop sending isochronous
- // data. If the channel is a listener, this procedure will stop the local
- // isochronous port.
- //
-
- static OSStatus FWCCMStopIsochPort(
- FWClientIsochPortControlParamsPtr
- pIsochPortControlParams,
- UInt32 *pCommandAcceptance)
- {
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCommandObjectID asynchCommandObjectID;
- FWCommandObjectID isochPortCommandObjectID;
- Boolean portIsTalker;
- UInt32 *pFWCCMReg;
- OSStatus status = noErr;
-
- // DebugStr ((ConstStr255Param) "\pFWCCMStopIsochPort");
-
- // Get our driver data.
- pFWCCMDriverData = (FWCCMDriverDataPtr)
- pIsochPortControlParams->fwClientInterfaceParams.fwClientSpecificData;
-
- // Get our VDig data from refCon.
- pFWCCMVDigData = (FWCCMVDigDataPtr) pIsochPortControlParams->fwClientIsochPortParams.refCon;
-
- // Is this request for the talking port?
- portIsTalker = pIsochPortControlParams->fwClientIsochPortParams.portIsTalker;
-
- if (portIsTalker)
- {
- // Send an async write packet to ISO_EN register.
- pFWCCMReg = &(pFWCCMVDigData->fwCCMReg);
- *pFWCCMReg = 0x00000000;
- asynchCommandObjectID = pFWCCMVDigData->stopAsynchCommandObjectID;
- FWSetFWCommandCompletionProcData
- (asynchCommandObjectID,
- (UInt32) pIsochPortControlParams->fwClientInterfaceParams.fwClientCommandID);
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0614,
- (Ptr) pFWCCMReg,
- 4);
-
- // Write register.
- FWCCMDelayForHardware (100*durationMillisecond);
- status = FWWrite (asynchCommandObjectID);
- }
- else
- {
- // Set up command object to stop port.
- isochPortCommandObjectID = pFWCCMVDigData->isochPortCommandObjectID;
- FWSetFWCommandParams
- (isochPortCommandObjectID,
- (FWReferenceID) pFWCCMDriverData->fwDriverID,
- 0,
- FWCCMClientCommandCompletionProc,
- (UInt32) pIsochPortControlParams->fwClientInterfaceParams.fwClientCommandID);
- FWSetIsochPortCommandIsochPortID
- (isochPortCommandObjectID, pFWCCMVDigData->isochPortID);
-
- // Send command to stop port.
- status = FWStopLocalIsochronousPort (isochPortCommandObjectID);
- }
-
- // Return command acceptance.
- //zzz is this the right way? If we've completed the command, we can accept more.
- *pCommandAcceptance = kFWClientCommandAcceptNoMore;
-
- return status;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMIsochChannelForceStopNotification
- //
- // This routine is called when the isochronous channel is forcefully stopped.
- //
-
- static OSStatus FWCCMIsochChannelForceStopNotification(
- IsochChannelID isochChannelID,
- UInt32 stopCondition)
- {
- OSStatus status = noErr;
-
- return status;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // ComponentInterface
- //
- // Main entry point for FireWire CCM VDig component.
- //
-
- pascal ComponentResult ComponentInterface(
- ComponentParameters *pComponentParams,
- Handle componentSpecificData)
- {
- ComponentResult result = noErr;
-
- // Create a routine descriptor based on interface selector.
- switch (pComponentParams->what)
- {
- case kComponentOpenSelect :
- result = FWCCMOpen
- (componentSpecificData,
- (ComponentOpenParamsPtr) pComponentParams->params);
- break;
-
- case kComponentCloseSelect :
- result = FWCCMClose
- (componentSpecificData,
- (ComponentCloseParamsPtr) pComponentParams->params);
- break;
-
- case kComponentCanDoSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pComponentCanDo");
- result = -1;
- /*zzz*/
- break;
-
- case kComponentVersionSelect :
- result = FWCCMVersion (componentSpecificData);
- break;
-
- case kComponentTargetSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pComponentTargetSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kComponentRegisterSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pComponentRegisterSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kVDGetActiveSrcRectSelect :
- result = FWCCMGetActiveSrcRect
- (componentSpecificData,
- (VDigGetActiveSrcRectParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetDigitizerRectSelect :
- result = FWCCMSetDigitizerRect
- (componentSpecificData,
- (VDigSetDigitizerRectParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetHueSelect :
- result = FWCCMSetHue
- (componentSpecificData,
- (VDigSetHueParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetSaturationSelect :
- result = FWCCMSetSaturation
- (componentSpecificData,
- (VDigSetSaturationParamsPtr) pComponentParams->params);
- break;
-
- case kVDGetHueSelect :
- result = FWCCMGetHue
- (componentSpecificData,
- (VDigGetHueParamsPtr) pComponentParams->params);
- break;
-
- case kVDGetSaturationSelect :
- result = FWCCMGetSaturation
- (componentSpecificData,
- (VDigGetSaturationParamsPtr) pComponentParams->params);
- break;
-
- case kVDGrabOneFrameSelect :
- result = FWCCMGrabOneFrame (componentSpecificData);
- break;
-
- case kVDGetDigitizerInfoSelect :
- result = FWCCMGetDigitizerInfo
- (componentSpecificData,
- (VDigGetDigitizerInfoParamsPtr) pComponentParams->params);
- break;
-
- case kVDGetCurrentFlagsSelect :
- result = FWCCMGetCurrentFlags
- (componentSpecificData,
- (VDigGetCurrentFlagsParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetPlayThruDestinationSelect :
- result = FWCCMSetPlayThruDestination
- (componentSpecificData,
- (VDigSetPlayThruDestinationParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetPlayThruOnOffSelect :
- result = FWCCMSetPlayThruOnOff
- (componentSpecificData,
- (VDigSetPlayThruOnOffParamsPtr) pComponentParams->params);
- break;
-
- case kVDPreflightDestinationSelect :
- result = FWCCMPreflightDestination
- (componentSpecificData,
- (VDigPreflightDestinationParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetBlackLevelValueSelect :
- result = FWCCMSetBlackLevelValue
- (componentSpecificData,
- (VDigSetBlackLevelValueParamsPtr) pComponentParams->params);
- break;
-
- case kVDGetBlackLevelValueSelect :
- result = FWCCMGetBlackLevelValue
- (componentSpecificData,
- (VDigGetBlackLevelValueParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetWhiteLevelValueSelect :
- result = FWCCMSetWhiteLevelValue
- (componentSpecificData,
- (VDigSetWhiteLevelValueParamsPtr) pComponentParams->params);
- break;
-
- case kVDGetWhiteLevelValueSelect :
- result = FWCCMGetWhiteLevelValue
- (componentSpecificData,
- (VDigGetWhiteLevelValueParamsPtr) pComponentParams->params);
- break;
-
- case kVDGetNumberOfInputsSelect :
- result = FWCCMGetNumberOfInputs
- (componentSpecificData,
- (VDigGetNumberOfInputsParamsPtr) pComponentParams->params);
- break;
-
- case kVDGetInputSelect :
- result = FWCCMGetInput
- (componentSpecificData,
- (VDigGetInputParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetInputStandardSelect :
- result = FWCCMSetInputStandard
- (componentSpecificData,
- (VDigSetInputStandardParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetupBuffersSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pSetup buffers");
- /*zzz*/
- result = FWCCMSetupBuffers
- (componentSpecificData,
- (VDigSetupBuffersParamsPtr) pComponentParams->params);
- break;
-
- case kVDGrabOneFrameAsyncSelect :
- result = FWCCMGrabOneFrameAsync
- (componentSpecificData,
- (VDigGrabOneFrameAsyncParamsPtr) pComponentParams->params);
- break;
-
- case kVDDoneSelect :
- result = FWCCMDone
- (componentSpecificData,
- (VDigDoneParamsPtr) pComponentParams->params);
- break;
-
- case kVDSetFrameRateSelect :
- result = FWCCMSetFrameRate
- (componentSpecificData,
- (VDigSetFrameRateParamsPtr) pComponentParams->params);
- break;
-
- case kVDReleaseAsyncBuffersSelect :
- result = FWCCMReleaseAsyncBuffers (componentSpecificData);
- break;
-
- case kVDGetFieldPreferenceSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pkVDGetFieldPreferenceSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kVDGetInputFormatSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pkVDGetInputFormatSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kVDGetVBlankRectSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pkVDGetVBlankRectSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kVDSetInputSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pkVDSetInputSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kVDGetDigitizerRectSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pkVDGetDigitizerRectSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kVDGetMaxSrcRectSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pkVDGetMaxSrcRectSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kVDGetPlayThruDestinationSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pkVDGetPlayThruDestinationSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kVDGetVideoDefaultsSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pkVDGetVideoDefaultsSelect");
- result = -1;
- /*zzz*/
- break;
-
- case kVDSetFieldPreferenceSelect :
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pkVDSetFieldPreferenceSelect");
- result = -1;
- /*zzz*/
- break;
-
- default :
- /*zzz*/
- //zzzsprintf (DebugStrStatus, "Unknown selector %lx", (long) pComponentParams->what);
- //zzzDebugStrStatus ((ConstStr255Param) c2pstr (DebugStrStatus));
- /*zzz*/
- result = digiUnimpErr;//zzz is this right for all calls???
- break;
- }
-
- return result;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMOpen
- //
- // Open routine for FireWire CCM VDig component.
- //
-
- static pascal ComponentResult FWCCMOpen(
- Handle componentSpecificData,
- ComponentOpenParamsPtr pComponentOpenParams)
- {
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCCMVDigDataPtr pFWCCMVDigData;
- Handle fwCCMVDigDataHandle = nil;
- CSRROMEntryIterator csrROMIterator = kInvalidCSRROMIterator;
- CSRROMEntryID csrRegBaseEntryID = kInvalidCSRROMEntryID;
- CSRROMSearchCriteria searchCriteria;
- Ptr frameBuf;
- UInt16 *yuvToRGB16Table;
- UInt32 *yuvToRGB32Table;
- FWCommandObjectID asynchCommandObjectID;
- IsochChannelID isochChannelID;
- DCLCommandPtr dclList;
- DCLCommandPtr *updateDCLList;
- UInt32 fwCCMReg;
- UInt8 Y, uU, uV;
- SInt8 U, V;
- SInt32 R, G, B;
- UInt32 yuv;
- Boolean done;
- CSRNodeUniqueID uniqueID;
- UInt32 beta3yuvEncoding;
- UInt32 i;
- ComponentResult result = noErr;
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pComponentOpen");
- /*zzz*/
-
- // We can only have one owner at a time.
- if (CountComponentInstances ((Component) pComponentOpenParams->componentInstance) > 1)
- result = -1;//zzz is there something better?
-
- // Get driver data.
- pFWCCMDriverData = gpFWCCMDriverData;
-
- // Allocate VDig data.
- if (result == noErr)
- {
- fwCCMVDigDataHandle = NewHandleClear (sizeof (FWCCMVDigData));
- if (fwCCMVDigDataHandle != nil)
- {
- MoveHHi (fwCCMVDigDataHandle);
- HLock (fwCCMVDigDataHandle);
- pFWCCMVDigData = (FWCCMVDigDataPtr) *fwCCMVDigDataHandle;
- pFWCCMDriverData->pFWCCMVDigData = pFWCCMVDigData;
- }
- else
- {
- result = memFullErr;
- }
- }
-
- ////////////////////////////////////////////////////////////////////////////
- //
- // Get register file base address offset.
- //
-
- // Create a CSR ROM search iterator.
- if (result == noErr)
- {
- result = FWCSRROMCreateIterator
- (&csrROMIterator,
- (FWReferenceID) pFWCCMDriverData->fwDriverID);
- }
-
- // Set iterator to start searching at our unit directory.
- if (result == noErr)
- {
- result = FWCSRROMSetIterator
- (csrROMIterator,
- pFWCCMDriverData->csrUnitID,
- kIterateDescendants);
- }
-
- // Search for register base address offset entry.
- if (result == noErr)
- {
- searchCriteria.csrROMSearchType = kCSRROMSearchForKey;
- searchCriteria.keyType = kCSROffsetKeyTypeBit;
- searchCriteria.keyHi = 0;
- searchCriteria.keyLo = (1 << 0);//zzz need def here
- result = FWCSRROMEntrySearch (csrROMIterator,
- kIterateContinue,
- &csrRegBaseEntryID,
- &done,
- &searchCriteria,
- nil,
- nil);
-
- if (done)
- result = notFoundErr;//zzz what should we really do?
- }
-
- // Register base address is address of register base address offset data.
- if (result == noErr)
- {
- result = FWCSRROMGetEntryDataAddress
- (csrRegBaseEntryID, &(pFWCCMDriverData->regBaseAddress));
- }
-
- // Clean up.
- if (csrROMIterator != kInvalidCSRROMIterator)
- FWCSRROMDisposeIterator (csrROMIterator);
- if (csrRegBaseEntryID != kInvalidCSRROMEntryID)
- FWCSRROMDisposeEntryID (csrRegBaseEntryID);
-
- // Create a queue for async grabs.
- if (result == noErr)
- result = PBQueueCreate(&(pFWCCMVDigData->vdigBufferRecQueue));
-
- // Create a DCL program.
- if (result == noErr)
- result = FWCreateDCLProgram (&(pFWCCMVDigData->dclProgramID));
-
- // Create list of DCLs.
- if (result == noErr)
- {
- dclList = (DCLCommandPtr) PoolAllocateResident (kDCLProgramSize, false);
- pFWCCMVDigData->dclList = dclList;
- if (!dclList)
- result = memFullErr;
- }
-
- // Create DCL update list.
- if (result == noErr)
- {
- updateDCLList = (DCLCommandPtr *)
- PoolAllocateResident (kNumTransferDCLs * sizeof (DCLCommandPtr), false);
- pFWCCMVDigData->updateDCLList = updateDCLList;
- if (!updateDCLList)
- result = memFullErr;
- }
-
- // Check "Unique" ID to see which YUV format to use.
- // All Beta 3 cameras have 0xFFFFFFFF for the low 32-bits of their unique
- // ID.
- if (result == noErr)
- {
- result = FWGetUniqueID ((FWReferenceID) pFWCCMDriverData->fwDriverID,
- &uniqueID);
-
- if (result == noErr)
- {
- if (uniqueID.lo == 0xFFFFFFFF)
- beta3yuvEncoding = true;
- else
- beta3yuvEncoding = false;
- }
- }
-
- // Allocate frame buffers.
- if (result == noErr)
- {
- for (i = 0; i < kNumFrameBufs; i++)
- {
- if (result == noErr)
- {
- frameBuf = PoolAllocateResident (kFrameBufSize, false);
- pFWCCMVDigData->frameBuf[i] = frameBuf;
- if (!frameBuf)
- result = memFullErr;
- }
- }
-
- // Clean up if we ran out of memory
- if (result == memFullErr)
- {
- for (i = 0; i < kNumFrameBufs; i++)
- if (pFWCCMVDigData->frameBuf[i])
- PoolDeallocate ((Ptr) pFWCCMVDigData->frameBuf[i]);
- }
- }
-
- // Write general-purpose DCL program.
- if (result == noErr)
- {
- FWCCMWriteDCLProgram (pFWCCMVDigData);
- }
-
- // Allocate and fill in YUV to RGB conversion table.
- // Create 16-bit 6:5:5 YUV to 32-bit RGB table.
- if (result == noErr)
- {
- yuvToRGB16Table =
- (UInt16 *) PoolAllocateResident ((1 << 16) * sizeof (UInt16), false);
- if (yuvToRGB16Table)
- {
- yuvToRGB32Table =
- (UInt32 *) PoolAllocateResident ((1 << 16) * sizeof (UInt32), false);
- if (yuvToRGB32Table)
- {
- pFWCCMVDigData->yuvToRGB16Table = yuvToRGB16Table;
- pFWCCMVDigData->yuvToRGB32Table = yuvToRGB32Table;
- for (yuv = 0; yuv < 0x10000; yuv++)
- {
- // Get YUV components from index.
- Y = (yuv >> 8) & 0x00FC;
- uU = (yuv >> 2) & 0x00F8;
- U = beta3yuvEncoding ?
- (SInt8) uU :
- (SInt8) (((int) uU) - 128);
- uV = (yuv << 3) & 0x00F8;
- V = beta3yuvEncoding ?
- (SInt8) uV :
- (SInt8) (((int) uV) - 128);
-
- // Compute RGB components from YUV components.
- R = Y + 1.398*V;
- G = Y - 0.3456*U - 0.7126*V;
- B = Y + 1.778*U;
-
- // Apply thresholding to RGB components.
- if (R > 255)
- R = 255;
- if (R < 0)
- R = 0;
- if (G > 255)
- G = 255;
- if (G < 0)
- G = 0;
- if (B > 255)
- B = 255;
- if (B < 0)
- B = 0;
-
- // Fill in table.
- yuvToRGB16Table[yuv] = ((R & 0xf8) << 7) |
- ((G & 0xf8) << 2) |
- ((B & 0xf8) >> 3); // (& is useless)
- yuvToRGB32Table[yuv] = (R << 16) | (G << 8) | B;
- }
- }
- else
- {
- PoolDeallocate ((Ptr) yuvToRGB16Table);
- result = memFullErr;
- }
- }
- else
- {
- result = memFullErr;
- }
- }
-
- // Allocate an isochronous channel to receive video data.
- if (result == noErr)
- {
- result = FWAllocateIsochronousChannelID
- (&isochChannelID, true, 10000000, kFWSpeed100MBit);
-
- if (result == noErr)
- pFWCCMVDigData->isochChannelID = isochChannelID;
- }
-
- // Set forceful stop notification procedure.
- if (result == noErr)
- {
- result = FWSetIsochChannelForceStopNotificationProc
- (isochChannelID, FWCCMIsochChannelForceStopNotification);
- }
-
- // Add camera as talking client.
- if (result == noErr)
- {
- result = FWAddIsochronousChannelClient
- (pFWCCMVDigData->isochChannelID,
- pFWCCMDriverData->fwDriverID,
- (UInt32) pFWCCMVDigData,
- true);
- }
-
- // Add local node as listening client.
- if (result == noErr)
- {
- result = FWAddIsochronousChannelClient
- (pFWCCMVDigData->isochChannelID,
- pFWCCMDriverData->fwDriverID,
- (UInt32) pFWCCMVDigData,
- false);
- }
-
- // Allocate FireWire command object for sending asynchronous packets.
- if (result == noErr)
- {
- result = FWAllocateAsynchCommandObject (&asynchCommandObjectID);
- if (result == noErr)
- pFWCCMVDigData->asynchCommandObjectID = asynchCommandObjectID;
- }
-
- // Set up FireWire command object for sending asynchronous packets.
- if (result == noErr)
- {
- FWSetFWCommandParams (asynchCommandObjectID,
- (FWReferenceID) pFWCCMDriverData->fwDriverID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetAsynchCommandMaxRetries (asynchCommandObjectID, 8);
- }
-
- // Allocate FireWire command object for sending camera start asynchronous packets.
- if (result == noErr)
- {
- result = FWAllocateAsynchCommandObject (&asynchCommandObjectID);
- if (result == noErr)
- pFWCCMVDigData->startAsynchCommandObjectID = asynchCommandObjectID;
- }
-
- // Set up FireWire command object for sending camera start asynchronous packets.
- if (result == noErr)
- {
- FWSetFWCommandParams (asynchCommandObjectID,
- (FWReferenceID) pFWCCMDriverData->fwDriverID,
- 0,
- FWCCMClientCommandCompletionProc,
- 0);
- FWSetAsynchCommandMaxRetries (asynchCommandObjectID, 8);
- }
-
- // Allocate FireWire command object for sending camera stop asynchronous packets.
- if (result == noErr)
- {
- result = FWAllocateAsynchCommandObject (&asynchCommandObjectID);
- if (result == noErr)
- pFWCCMVDigData->stopAsynchCommandObjectID = asynchCommandObjectID;
- }
-
- // Set up FireWire command object for sending camera stop asynchronous packets.
- if (result == noErr)
- {
- FWSetFWCommandParams (asynchCommandObjectID,
- (FWReferenceID) pFWCCMDriverData->fwDriverID,
- 0,
- FWCCMClientCommandCompletionProc,
- 0);
- FWSetAsynchCommandMaxRetries (asynchCommandObjectID, 8);
- }
-
- // Allocate FireWire command object for sending isoch channel commands.
- if (result == noErr)
- {
- result = FWAllocateIsochChannelCommandObject
- (&(pFWCCMVDigData->isochChannelCommandObjectID));
- }
-
- // Allocate FireWire command object for sending asynchronous start isoch channel commands.
- if (result == noErr)
- {
- result = FWAllocateIsochChannelCommandObject
- (&(pFWCCMVDigData->startIsochChannelCommandObjectID));
- }
-
- // Allocate FireWire command object for sending asynchronous stop isoch channel commands.
- if (result == noErr)
- {
- result = FWAllocateIsochChannelCommandObject
- (&(pFWCCMVDigData->stopIsochChannelCommandObjectID));
- }
-
- // Allocate FireWire command object for sending isoch port commands
- // synchronously.
- if (result == noErr)
- {
- result = FWAllocateIsochPortCommandObject
- (&(pFWCCMVDigData->isochPortCommandObjectID));
- }
-
- // Set camera to 30 fps.
- if (result == noErr)
- {
- fwCCMReg = 0x80000000;
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0600,
- (Ptr) &fwCCMReg,
- 4);
-
- FWCCMDelayForHardware (100*durationMillisecond);
- result = FWWrite (asynchCommandObjectID);
- }
-
- // Set camera to 320 x 240 4:2:2 YUV.
- if (result == noErr)
- {
- fwCCMReg = 0x20000000;
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0604,
- (Ptr) &fwCCMReg,
- 4);
-
- FWCCMDelayForHardware (100*durationMillisecond);
- result = FWWrite (asynchCommandObjectID);
- }
-
- // Initialize VDig data.
- //zzz defs???
- if (result == noErr)
- {
- pFWCCMVDigData->pFWCCMDriverData = pFWCCMDriverData;
- pFWCCMVDigData->digitizerRect.top = 0;
- pFWCCMVDigData->digitizerRect.left = 0;
- pFWCCMVDigData->digitizerRect.bottom = 240;
- pFWCCMVDigData->digitizerRect.right = 320;
- }
-
- // Set component storage.
- if (result == noErr)
- {
- SetComponentInstanceStorage (pComponentOpenParams->componentInstance,
- fwCCMVDigDataHandle);
- }
-
- /*zzz*/
- #if 0
- // Clean up on error.
- if (result != noErr)
- {
-
- //zzz Note, the large memory allocs are cleaned up above if we fail
- // due to running out of memory (but not for any other reason).
-
- if (fwCCMVDigDataHandle != nil)
- DisposeHandle (fwCCMVDigDataHandle);
- }
- #endif
- /*zzz*/
-
- return result;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMWriteDCLProgram
- //
- // This routine is called once, each time we are opened. It constructs a DCL
- // program suitable for all three kinds of receive (playthrough, sync grab,
- // and async grab). As the usage changes, only the callProc will be varied (but
- // not while the DCL program actually runs).
- //
- // The DCL program consists of consecutive frame-sized sets of receive buffers.
- // If we can't keep up with the received data, whole frames will be skipped.
- // But, we never skip a frame and then immediately want one that isn't there,
- // because we have a total of three frames.
- //
- // The high level structure looks like this:
- // Receive frame 1, branch to frame 2.
- // Receive frame 2, branch to frame 3.
- // Receive frame 3, branch to frame 3.
- //
- // ** Note: Frame 3 will be overwritten with frames 4, 5, 6, etc., unless we
- // change the branch that follows it, before that branch is reached.
- // Our goal is to do so, unless the CPU can't keep up.
- //
- // Once frame 1 has been received and processed, and the buffer is again
- // available, the DMA is running somewhere in frame 2 or 3. The branches
- // are then changed so that the high-level structure now looks like this:
- // Receive frame 1, branch to frame 1.
- // Receive frame 2, branch to frame 3.
- // Receive frame 3, branch to frame 1.
- //
- // If we had only two frame buffers, and the CPU speed varied (due to other loads)
- // and we had to sometimes skip frames, we might have the following sequence of
- // events: We are processing frame 1. Frame 2 completes, and the DMA starts to
- // receive frame 3 into the same buffer. But now we get full use of the CPU for
- // a while. We wrap up frame 1, and charge into frame 3 - and we overtake the DMA,
- // which is still filling in frame 3. So we glitch the video, because we'll show an
- // image that is partly frame 3 and partly frame 2. The three-buffer solution used
- // here prevents this problem.
- //
- // The lower level structure of the DCL program for a single frame looks like this:
- // kDCLLabelOp "preFrame"
- // kDCLReceivePacketStartOp x 240
- // kDCLJumpOp
- // kDCLLabelOp "postFrame"
- // kDCLUpdateDCLListOp
- // kDCLCallProcOp
- //
- // Usually, the Jump points to the "postFrame" label that follows it, meaning the
- // jump has no real effect. But in the "overflow" frame at the end of the DCL program,
- // the Jump points to the "preFrame" label that heads the frame, making the DMA fill
- // the same buffer again. Because the Jump takes place before the update and the
- // callProc, these tasks can be avoided when a frame of data is overwritten, to
- // save time (and maybe help catch up).
- //
- // Note that while the high-level description shows a branch to the next frame, the
- // actual Jump normally just moves execution forward by one DCL. After each callProc,
- // the DCLs for the next frame will begin. [Except at the end of program memory,
- // where there is an extra Jump back to the top of the DCL program.]
- //
- // The use of large, frame-sized blocks of DCLs serves three purposes. First, it allows
- // for the preservation of vertical lock in systems such as Pele that cannot detect
- // the start-of-frame sync pattern in an already-running DMA program. Second, even for
- // systems that could detect sync (OpenHCI, Lynx), this DMA arrangement neatly skips
- // whole frames of data, without forcing the CPU to spend extra time taking callProcs
- // for data that will not be used. Finally, the use of three frames means that we can
- // degrade gracefully when we cannot keep up. For example, with a two-frame (or smaller)
- // program, if we can't keep up with 30 fps, we'll end up dropping every other frame
- // and netting about 15 fps. The three-frame program, however, can degrade to 29, 28,
- // or some other fps, because it has more elasticity.
-
- static void FWCCMWriteDCLProgram(
- FWCCMVDigDataPtr pFWCCMVDigData)
- {
- Ptr pDCLCommand;
- DCLLabelPtr pStartDCLLabel,
- pPreFrameDCLLabel,
- pPostFrameDCLLabel;
- DCLTransferPacketPtr pDCLTransferPacket,
- pFirstDCLTransferPacket;
- DCLCallProcPtr pDCLCallProc;
- DCLJumpPtr pDCLJump;
- DCLUpdateDCLListPtr pDCLUpdateDCLList;
- DCLCommandPtr *updateDCLList,
- *frameUpdateDCLList;
- UInt32 updateListSize;
- Ptr frameBuffer;
- UInt32 frameNum,
- packetNum;
-
- DebugStrStatus ((ConstStr255Param) "\pFWCCMWriteDCLProgram");
-
- pDCLCommand = (Ptr) pFWCCMVDigData->dclList;
-
- // We build several update lists by carving up this block of memory:
- updateDCLList = pFWCCMVDigData->updateDCLList;
-
- // Create label for start of program.
- pStartDCLLabel = (DCLLabelPtr) pDCLCommand;
- pDCLCommand += sizeof (DCLLabel);
- pStartDCLLabel->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
- pStartDCLLabel->opcode = kDCLLabelOp;
-
- // Create kNumFrameBufs (3) buffer lists of kNumPacketsPerFrameBuf (240)
- // packets each.
- for (frameNum = 0; frameNum < kNumFrameBufs; frameNum++)
- {
- frameBuffer = pFWCCMVDigData->frameBuf[frameNum];
-
- // Create label for start of frame.
- pPreFrameDCLLabel = (DCLLabelPtr) pDCLCommand;
- pDCLCommand += sizeof (DCLLabel);
- pPreFrameDCLLabel->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
- pPreFrameDCLLabel->opcode = kDCLLabelOp;
-
- // Create transfer PCL for each packet.
- pFirstDCLTransferPacket = (DCLTransferPacketPtr) pDCLCommand;
- frameUpdateDCLList = updateDCLList;
- updateListSize = 0;
- for (packetNum = 0; packetNum < kNumPacketsPerFrameBuf; packetNum++)
- {
- // Receive one packet up to kReceiveCCMMaxPacketSize bytes.
- pDCLTransferPacket = (DCLTransferPacketPtr) pDCLCommand;
- pDCLCommand += sizeof (DCLTransferPacket);
- pDCLTransferPacket->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
- pDCLTransferPacket->opcode = kDCLReceivePacketStartOp;
- pDCLTransferPacket->buffer = frameBuffer;
- pDCLTransferPacket->size = kReceiveCCMMaxPacketSize;
- *updateDCLList++ = (DCLCommandPtr) pDCLTransferPacket;
- updateListSize++;
- frameBuffer += kReceiveCCMMaxPacketSize;
- }
-
- // Create jump DCL.
- // Normally just jump forward one DCL.
- // But, repeat the last buffer if we are running behind.
- pDCLJump = (DCLJumpPtr) pDCLCommand;
- pDCLCommand += sizeof (DCLJump);
- pDCLJump->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
- pDCLJump->opcode = kDCLJumpOp | kFWDCLOpDynamicFlag;
- pDCLJump->pJumpDCLLabel = (DCLLabelPtr) pDCLCommand; // modify later
-
- // Create label for end of frame.
- pPostFrameDCLLabel = (DCLLabelPtr) pDCLCommand;
- pDCLCommand += sizeof (DCLLabel);
- pPostFrameDCLLabel->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
- pPostFrameDCLLabel->opcode = kDCLLabelOp;
-
- // Create update DCL list.
- pDCLUpdateDCLList = (DCLUpdateDCLListPtr) pDCLCommand;
- pDCLCommand += sizeof (DCLUpdateDCLList);
- pDCLUpdateDCLList->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
- pDCLUpdateDCLList->opcode = kDCLUpdateDCLListOp;
- pDCLUpdateDCLList->dclCommandList = frameUpdateDCLList;
- pDCLUpdateDCLList->numDCLCommands = updateListSize;
-
- // Call a function to consume the received data.
- pDCLCallProc = (DCLCallProcPtr) pDCLCommand;
- pDCLCommand += sizeof (DCLCallProc);
- pDCLCallProc->pNextDCLCommand = (DCLCommandPtr) pDCLCommand;
- pDCLCallProc->opcode = kDCLCallProcOp;
- pDCLCallProc->proc = 0; // fill in later
- pDCLCallProc->procData = (UInt32) pFWCCMVDigData; // all use this data
-
- // Record some information about this frame that we'll use later.
- pFWCCMVDigData->preFrameDCLLabel[frameNum] = pPreFrameDCLLabel;
- pFWCCMVDigData->firstDCLTransferPacket[frameNum] = pFirstDCLTransferPacket;
- pFWCCMVDigData->postFrameDCLJump[frameNum] = pDCLJump;
- pFWCCMVDigData->postFrameDCLLabel[frameNum] = pPostFrameDCLLabel;
- pFWCCMVDigData->postFrameDCLCallProc[frameNum] = pDCLCallProc;
- }
-
- // Create jump DCL to loop to the top of the program.
- pDCLJump = (DCLJumpPtr) pDCLCommand;
- pDCLCommand += sizeof (DCLJump); // unused
- pDCLJump->pNextDCLCommand = (DCLCommandPtr) nil; // end of program memory
- pDCLJump->opcode = kDCLJumpOp;
- pDCLJump->pJumpDCLLabel = pStartDCLLabel;
-
- // The DCL program is now ready to use, except that the callProcs have
- // not been filled in, and the jumps all point forward. (In normal use
- // one of the jumps will loop to the frame that was just completed.)
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetupDCLProgram
- //
- // This routine is called once each time we are going to start up the DCL
- // program. This routine sets the callProcs depending on the usage of
- // the program, and it resets all of the jumps within the program.
- //
- // See extensive comments in FWCCMWriteDCLProgram for more information.
- //
-
- static void FWCCMSetupDCLProgram(
- FWCCMVDigDataPtr pFWCCMVDigData,
- DCLCallCommandProcPtr callProc)
- {
- DCLLabelPtr pPreFrameDCLLabel,
- pPostFrameDCLLabel;
- DCLCallProcPtr pDCLCallProc;
- DCLJumpPtr pDCLJump;
- UInt32 frameNum;
-
- for (frameNum = 0; frameNum < kNumFrameBufs; frameNum++)
- {
- // Get DCL pointers we saved earlier:
- pPreFrameDCLLabel = pFWCCMVDigData->preFrameDCLLabel[frameNum];
- pDCLJump = pFWCCMVDigData->postFrameDCLJump[frameNum];
- pPostFrameDCLLabel = pFWCCMVDigData->postFrameDCLLabel[frameNum];
- pDCLCallProc = pFWCCMVDigData->postFrameDCLCallProc[frameNum];
-
- // Set the CallProc as given
- pDCLCallProc->proc = callProc;
-
- // Set the Jump forward
- pDCLJump->pJumpDCLLabel = pPostFrameDCLLabel;
- }
-
- // Change the last jump to loop on itself
- pDCLJump->pJumpDCLLabel = pPreFrameDCLLabel;
-
- // Do the first frame first
- pFWCCMVDigData->pendingFrameNum = 0;
- pFWCCMVDigData->pendingFrameCount = 0;
- pFWCCMVDigData->pendingFrameFragments = 0;
-
- // The DCL program is now ready to run.
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetDCLProgramEndFrame
- //
- // This routine rewrites the jumps in the running DCL program to place the
- // specified frame buffer at the end of the program, and make it loop to itself.
- // The previous self-looping end frame is also fixed up.
- //
- // See extensive comments in FWCCMWriteDCLProgram for more information.
- //
-
- static void FWCCMSetDCLProgramEndFrame(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 endFrameNum)
- {
- DCLProgramID dclProgramID;
- UInt32 prevFrameNum;
- DCLLabelPtr pPreFrameDCLLabel,
- pPostFrameDCLLabel;
- DCLJumpPtr pDCLJump;
-
- dclProgramID = pFWCCMVDigData->dclProgramID;
- prevFrameNum = (endFrameNum + (kNumFrameBufs - 1)) % kNumFrameBufs;
-
- // First make the new end frame loop to itself.
- pPreFrameDCLLabel = pFWCCMVDigData->preFrameDCLLabel[endFrameNum];
- pDCLJump = pFWCCMVDigData->postFrameDCLJump[endFrameNum];
-
- FWModifyDCLJump (dclProgramID, pDCLJump, pPreFrameDCLLabel);
-
- // Now make the previous end frame no longer loop to itself.
- pPostFrameDCLLabel = pFWCCMVDigData->postFrameDCLLabel[prevFrameNum];
- pDCLJump = pFWCCMVDigData->postFrameDCLJump[prevFrameNum];
-
- FWModifyDCLJump (dclProgramID, pDCLJump, pPostFrameDCLLabel);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMClose
- //
- // Close routine for FireWire CCM VDig component.
- //
-
- static pascal ComponentResult FWCCMClose(
- Handle componentSpecificData,
- ComponentCloseParamsPtr pComponentCloseParams)
- {
- FWCommandObjectID isochChannelCommandObjectID;
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCCMDriverDataPtr pFWCCMDriverData;
- UInt32 i;
-
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pClose component");
- /*zzz*/
- // Deallocate our data.
- if (componentSpecificData != nil)
- {
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Release isochronous channel.
- if (pFWCCMVDigData->channelInitialized)
- {
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- pFWCCMVDigData->channelActive = false;
- FWStopIsochronousChannel (isochChannelCommandObjectID);
-
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- FWReleaseIsochronousChannel (isochChannelCommandObjectID);
- }
-
- // Deallocate FireWire command object for sending isoch port commands.
- if (pFWCCMVDigData->isochPortCommandObjectID != kInvalidFWCommandObjectID)
- FWDeallocateFWCommandObject (pFWCCMVDigData->isochPortCommandObjectID);
-
- // Deallocate FireWire command object for sending asynchronous stop
- // isoch channel commands.
- if (pFWCCMVDigData->stopIsochChannelCommandObjectID != kInvalidFWCommandObjectID)
- FWDeallocateFWCommandObject (pFWCCMVDigData->stopIsochChannelCommandObjectID);
-
- // Deallocate FireWire command object for sending asynchronous start
- // isoch channel commands.
- if (pFWCCMVDigData->startIsochChannelCommandObjectID != kInvalidFWCommandObjectID)
- FWDeallocateFWCommandObject (pFWCCMVDigData->startIsochChannelCommandObjectID);
-
- // Deallocate FireWire command object for sending isoch channel commands.
- if (pFWCCMVDigData->isochChannelCommandObjectID != kInvalidFWCommandObjectID)
- FWDeallocateFWCommandObject (pFWCCMVDigData->isochChannelCommandObjectID);
-
- // Deallocate FireWire command object for sending asynchronous packets.
- if (pFWCCMVDigData->asynchCommandObjectID != kInvalidFWCommandObjectID)
- FWDeallocateFWCommandObject (pFWCCMVDigData->asynchCommandObjectID);
-
- // Deallocate FireWire command object for sending camera start asynchronous
- // packets.
- if (pFWCCMVDigData->startAsynchCommandObjectID != kInvalidFWCommandObjectID)
- FWDeallocateFWCommandObject (pFWCCMVDigData->startAsynchCommandObjectID);
-
- // Deallocate FireWire command object for sending camera stop asynchronous
- // packets.
- if (pFWCCMVDigData->stopAsynchCommandObjectID != kInvalidFWCommandObjectID)
- FWDeallocateFWCommandObject (pFWCCMVDigData->stopAsynchCommandObjectID);
-
- // Deallocate isochronous channel ID for receiving video data.
- if (pFWCCMVDigData->isochChannelID != kInvalidIsochChannelID)
- FWDeallocateIsochronousChannelID (pFWCCMVDigData->isochChannelID);
-
- // Deallocate YUV to RGB tables.
- if (pFWCCMVDigData->yuvToRGB32Table)
- PoolDeallocate ((Ptr) pFWCCMVDigData->yuvToRGB32Table);
-
- if (pFWCCMVDigData->yuvToRGB16Table)
- PoolDeallocate ((Ptr) pFWCCMVDigData->yuvToRGB16Table);
-
- // Deallocate frame buffers.
- for (i = 0; i < kNumFrameBufs; i++)
- if (pFWCCMVDigData->frameBuf[i])
- PoolDeallocate ((Ptr) pFWCCMVDigData->frameBuf[i]);
-
- // Dispose of DCL program.
- if (pFWCCMVDigData->dclProgramID != kInvalidDCLProgramID)
- FWDisposeDCLProgram (pFWCCMVDigData->dclProgramID);
-
- // Deallocate DCL update list
- if (pFWCCMVDigData->updateDCLList)
- PoolDeallocate ((Ptr) pFWCCMVDigData->updateDCLList);
-
- // Deallocate DCL list.
- if (pFWCCMVDigData->dclList)
- PoolDeallocate ((Ptr) pFWCCMVDigData->dclList);
-
- // Deallocate async queue.
- if (pFWCCMVDigData->vdigBufferRecQueue)
- PBQueueDelete (pFWCCMVDigData->vdigBufferRecQueue);
-
- if (pFWCCMDriverData)
- pFWCCMDriverData->pFWCCMVDigData = nil;
- DisposeHandle (componentSpecificData);
- }
-
- return noErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMVersion
- //
- // This routine returns the component version.
- //
-
- static pascal long FWCCMVersion(
- Handle componentSpecificData)
- {
- return (vdigInterfaceRev << 16) | 0; //zzz define code rev
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMInitializeDriver
- //
- // This routine does some driver initialization. It will register with the
- // FireWire family.
- //zzz need to be able to unregister driver on error.
- //
-
- static pascal ComponentResult FWCCMInitializeDriver(
- RegEntryIDPtr pRegEntryID)
- {
- FWDriverID fwDriverID;
- ComponentResult result = noErr;
-
- // Allocate driver data record.
- gpFWCCMDriverData =
- (FWCCMDriverDataPtr) PoolAllocateResident (sizeof (FWCCMDriverData), true);
- if (gpFWCCMDriverData == nil)
- result = memFullErr;
-
- // Register with the FireWire family.
- if (result == noErr)
- {
- result = FWRegisterDriver (pRegEntryID,
- &fwDriverID,
- &(gpFWCCMDriverData->csrUnitID),
- (UInt32) gpFWCCMDriverData);
- if (result == noErr)
- gpFWCCMDriverData->fwDriverID = fwDriverID;
- }
-
- // Set reset bus management notify interface proc.
- if (result == noErr)
- {
- result = FWSetFWClientBusManagementNotifyProc
- ((FWReferenceID) fwDriverID, FWCCMBusManagementNotify);
- }
-
- // Set initialize isoch port interface proc.
- if (result == noErr)
- {
- result = FWSetFWClientInitIsochPortProc
- ((FWReferenceID) fwDriverID, FWCCMInitIsochPort);
- }
-
- // Set release isoch port interface proc.
- if (result == noErr)
- {
- result = FWSetFWClientReleaseIsochPortProc
- ((FWReferenceID) fwDriverID, FWCCMReleaseIsochPort);
- }
-
- // Set start isoch port interface proc.
- if (result == noErr)
- {
- result = FWSetFWClientStartIsochPortProc
- ((FWReferenceID) fwDriverID, FWCCMStartIsochPort);
- }
-
- // Set stop isoch port interface proc.
- if (result == noErr)
- {
- result = FWSetFWClientStopIsochPortProc
- ((FWReferenceID) fwDriverID, FWCCMStopIsochPort);
- }
-
- // Clean up on error.
- if ((result != noErr) && (gpFWCCMDriverData != nil))
- FWCCMFinalizeDriver (pRegEntryID);
-
- return result;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMFinalizeDriver
- //
- // This routine does some driver finalization. It will unregister with the
- // FireWire family.
- //
-
- static pascal ComponentResult FWCCMFinalizeDriver(
- RegEntryIDPtr pRegEntryID)
- {
- ComponentResult result = noErr;
-
- if (gpFWCCMDriverData != nil)
- {
- // Unregister with the FireWire family.
- if (gpFWCCMDriverData->fwDriverID != kInvalidFWDriverID)
- FWUnregisterDriver (gpFWCCMDriverData->fwDriverID);
-
- // Deallocate driver data record.
- PoolDeallocate ((Ptr) gpFWCCMDriverData);
- gpFWCCMDriverData = nil;
- }
-
- return result;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGetActiveSrcRect
- //
- // This routine returns the size and location of the active source
- // rectangle.
- //
-
- static pascal VideoDigitizerError FWCCMGetActiveSrcRect(
- Handle componentSpecificData,
- VDigGetActiveSrcRectParamsPtr
- pVDigGetActiveSrcRectParams)
- {
- Rect *pActiveSrcRect;
- VideoDigitizerError vdigErr = noErr;
-
- // Validate inputNum.
- if (pVDigGetActiveSrcRectParams->inputNum > 0)
- {
- vdigErr = -1;//zzz is there something better???
- }
-
- // Return active source rect.
- //zzz should get this out of some data structure.
- if (vdigErr == noErr)
- {
- pActiveSrcRect = pVDigGetActiveSrcRectParams->pActiveSrcRect;
- pActiveSrcRect->top = 0;
- pActiveSrcRect->left = 0;
- pActiveSrcRect->bottom = 240;
- pActiveSrcRect->right = 320;
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetDigitizerRect
- //
- // This routine sets the current digitizer rectangle.
- //zzz validate rect.
- //
-
- static pascal VideoDigitizerError FWCCMSetDigitizerRect(
- Handle componentSpecificData,
- VDigSetDigitizerRectParamsPtr
- pVDigSetDigitizerRectParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- VideoDigitizerError vdigErr = noErr;
-
- // Get VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Set digitizer rect.
- pFWCCMVDigData->digitizerRect = *(pVDigSetDigitizerRectParams->pDigitizerRect);
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGetDigitizerInfo
- //
- // This routine returns information about the VDig.
- //
-
- static pascal VideoDigitizerError FWCCMGetDigitizerInfo(
- Handle componentSpecificData,
- VDigGetDigitizerInfoParamsPtr
- pVDigGetDigitizerInfoParams)
- {
- DigitizerInfo *pDigitizerInfo;
- VideoDigitizerError vdigErr = noErr;
-
- // Fill out info record.
- //zzz need to set some things for real
- pDigitizerInfo = pVDigGetDigitizerInfoParams->pDigitizerInfo;
- pDigitizerInfo->vdigType = vdTypeBasic;
- pDigitizerInfo->inputCapabilityFlags = digiInDoesNTSC | /*zzz just fake it*/
- digiInDoesComponent |
- digiInDoesBW |
- digiInDoesColor;
- pDigitizerInfo->outputCapabilityFlags = digiOutDoes16 |
- digiOutDoes32 |
- digiOutDoesAsyncGrabs |
- digiOutDoesHWPlayThru |
- digiOutDoesHW_DMA;
- pDigitizerInfo->inputCurrentFlags = digiInDoesNTSC | /*zzz just fake it */
- digiInDoesComponent |
- digiInDoesColor;
- pDigitizerInfo->outputCurrentFlags = digiOutDoes16 |
- digiOutDoes32 |
- digiOutDoesAsyncGrabs |
- digiOutDoesHWPlayThru |
- digiOutDoesHW_DMA;
- pDigitizerInfo->slot = 0; /*zzz doesn't really have a slot. */
- pDigitizerInfo->gdh = nil;
- pDigitizerInfo->maskgdh = nil;
- pDigitizerInfo->minDestHeight = 240;
- pDigitizerInfo->minDestWidth = 320;
- pDigitizerInfo->maxDestHeight = 480;
- pDigitizerInfo->maxDestWidth = 640;
- pDigitizerInfo->blendLevels = 0;
- pDigitizerInfo->reserved = 0;
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGetCurrentFlags
- //
- // This routine returns the current state of the VDig.
- //
-
- static pascal VideoDigitizerError FWCCMGetCurrentFlags(
- Handle componentSpecificData,
- VDigGetCurrentFlagsParamsPtr
- pVDigGetCurrentFlagsParams)
- {
- VideoDigitizerError vdigErr = noErr;
-
- //zzz do these for real
- *(pVDigGetCurrentFlagsParams->pInputCurrentFlags) =
- digiInDoesNTSC | /*zzz just fake it */
- digiInDoesComponent |
- digiInDoesColor;
-
- *(pVDigGetCurrentFlagsParams->pOutputCurrentFlags) =
- digiOutDoes16 |
- digiOutDoes32 |
- digiOutDoesAsyncGrabs |
- digiOutDoesHWPlayThru |
- digiOutDoesHW_DMA;
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetPlayThruDestination
- //
- // This function establishes the destination settings for the VDig.
- //zzz Should do some parameter checking.
- //zzz Should we CopyPixMap hDestPixMap or just copy the handle???
- //
-
- static pascal VideoDigitizerError FWCCMSetPlayThruDestination(
- Handle componentSpecificData,
- VDigSetPlayThruDestinationParamsPtr
- pVDigSetPlayThruDestinationParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- VdigBufferRecListHandle bufferList = nil;
- VideoDigitizerError vdigErr = noErr;
-
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pFWCCMSetPlayThruDestination");
- /*zzz*/
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get pix map and dest rect.
- pFWCCMVDigData->hDestPixMap = pVDigSetPlayThruDestinationParams->hDestPixMap;
- pFWCCMVDigData->destRect = *(pVDigSetPlayThruDestinationParams->pDestRect);
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetPlayThruOnOff
- //
- // This function controls continuous digitization.
- //
- // Note: Because all of the work in playthrough is triggered by interrupts from
- // the isochronous receive DMA, if we are not able to keep up, we may saturate
- // the CPU and prevent the user from regaining control.
- //
- // One way to improve this would be to put a callProc at the tail of each frame
- // before the jump DCL. This callProc would not touch the data (the Update has
- // not been reached yet) but will make a note that the DMA made forward progress.
- // Getting the same such callProc twice in a row tells us we have fallen behind
- // and a frame was skipped. If that happens a lot, maybe we should yield the CPU.
- //
-
- static pascal VideoDigitizerError FWCCMSetPlayThruOnOff(
- Handle componentSpecificData,
- VDigSetPlayThruOnOffParamsPtr
- pVDigSetPlayThruOnOffParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCommandObjectID isochChannelCommandObjectID;
- VideoDigitizerError vdigErr = noErr;
-
- /*zzz*/
- if (pVDigSetPlayThruOnOffParams->state)
- DebugStrStatus ((ConstStr255Param) "\pFWCCMSetPlayThruOnOff on");
- else
- DebugStrStatus ((ConstStr255Param) "\pFWCCMSetPlayThruOnOff off");
- /*zzz*/
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Turn on or off.
- if (pVDigSetPlayThruOnOffParams->state)
- {
- // Release isochronous channel.
- if (pFWCCMVDigData->channelInitialized)
- {
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- pFWCCMVDigData->channelActive = false;
- FWStopIsochronousChannel (isochChannelCommandObjectID);
-
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- FWReleaseIsochronousChannel (isochChannelCommandObjectID);
- }
-
- // Reset the jumps and set the callprocs, and set start of DCL program:
- if (vdigErr == noErr)
- {
- FWCCMSetupDCLProgram (pFWCCMVDigData,
- (DCLCallCommandProcPtr) FWCCMPlayThruIsochHandler);
- vdigErr = FWSetDCLProgramStart (pFWCCMVDigData->dclProgramID,
- pFWCCMVDigData->dclList);
- }
-
- // Initialize isochronous channel.
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- vdigErr = FWInitializeIsochronousChannel (isochChannelCommandObjectID);
-
- if (vdigErr == noErr)
- {
- pFWCCMVDigData->channelInitialized = true;
- pFWCCMVDigData->currentLocation.v = 0;
- pFWCCMVDigData->currentLocation.h = 0;
- }
-
- // Start up isochronous channel.
- if (vdigErr == noErr)
- {
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- pFWCCMVDigData->channelActive = true;
- vdigErr = FWStartIsochronousChannel (isochChannelCommandObjectID);
- }
- }
- else
- {
- // Release isochronous channel.
- if (pFWCCMVDigData->channelInitialized)
- {
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- pFWCCMVDigData->channelActive = false;
- FWStopIsochronousChannel (isochChannelCommandObjectID);
-
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- FWReleaseIsochronousChannel (isochChannelCommandObjectID);
- }
- pFWCCMVDigData->channelInitialized = false;
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetHue
- //
- // This function sets the hue for the camera.
- //
-
- static pascal VideoDigitizerError FWCCMSetHue(
- Handle componentSpecificData,
- VDigSetHueParamsPtr pVDigSetHueParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCommandObjectID asynchCommandObjectID;
- UInt32 fwCCMReg;
- UInt32 minValue,
- maxValue;
- unsigned short *pHue;
- UInt32 hue;
- VideoDigitizerError vdigErr = noErr;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Read the min/max value for the hue register.
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0510,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- minValue = (fwCCMReg & 0x00FFF000) >> 12;
- maxValue = fwCCMReg & 0x0FFF;
-
- // Scale hue value.
- if (vdigErr == noErr)
- {
- pHue = pVDigSetHueParams->pHue;
- hue = minValue + (((*pHue)*(maxValue - minValue)) >> 16);
- }
-
- // Write the hue register in the camera.
- if (vdigErr == noErr)
- {
- fwCCMReg = 0x82000000 | hue;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0810,
- (Ptr) &fwCCMReg,
- 4);
-
- FWCCMDelayForHardware (100*durationMillisecond);
- vdigErr = FWWrite (asynchCommandObjectID);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetSaturation
- //
- // This function sets the saturation for the camera.
- //
-
- static pascal VideoDigitizerError FWCCMSetSaturation(
- Handle componentSpecificData,
- VDigSetSaturationParamsPtr pVDigSetSaturationParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCommandObjectID asynchCommandObjectID;
- UInt32 fwCCMReg;
- UInt32 minValue,
- maxValue;
- unsigned short *pSaturation;
- UInt32 saturation;
- VideoDigitizerError vdigErr = noErr;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Read the min/max value for the saturation register.
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0514,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- minValue = (fwCCMReg & 0x00FFF000) >> 12;
- maxValue = fwCCMReg & 0x0FFF;
-
- // Scale saturation value.
- if (vdigErr == noErr)
- {
- pSaturation = pVDigSetSaturationParams->pSaturation;
- saturation = minValue + (((*pSaturation)*(maxValue - minValue)) >> 16);
- }
-
- // Write the saturation register in the camera.
- if (vdigErr == noErr)
- {
- fwCCMReg = 0x82000000 | saturation;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0814,
- (Ptr) &fwCCMReg,
- 4);
-
- FWCCMDelayForHardware (100*durationMillisecond);
- vdigErr = FWWrite (asynchCommandObjectID);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGetHue
- //
- // This function gets the hue for the camera.
- //
-
- static pascal VideoDigitizerError FWCCMGetHue(
- Handle componentSpecificData,
- VDigGetHueParamsPtr pVDigGetHueParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCommandObjectID asynchCommandObjectID;
- UInt32 fwCCMReg;
- UInt32 minValue,
- maxValue;
- VideoDigitizerError vdigErr = noErr;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Read the min/max value for the hue register.
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0510,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- minValue = (fwCCMReg & 0x00FFF000) >> 12;
- maxValue = fwCCMReg & 0x0FFF;
-
- // Read the hue register in the camera.
- if (vdigErr == noErr)
- {
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0810,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- }
-
- // Return scaled result.
- if (vdigErr == noErr)
- {
- *(pVDigGetHueParams->pHue) =
- (((fwCCMReg & 0x0FFF) - minValue) << 16) / (maxValue - minValue);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGetSaturation
- //
- // This function gets the saturation for the camera.
- //
-
- static pascal VideoDigitizerError FWCCMGetSaturation(
- Handle componentSpecificData,
- VDigGetSaturationParamsPtr pVDigGetSaturationParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCommandObjectID asynchCommandObjectID;
- UInt32 fwCCMReg;
- UInt32 minValue,
- maxValue;
- VideoDigitizerError vdigErr = noErr;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Read the min/max value for the saturation register.
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0514,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- minValue = (fwCCMReg & 0x00FFF000) >> 12;
- maxValue = fwCCMReg & 0x0FFF;
-
- // Read the saturation register in the camera.
- if (vdigErr == noErr)
- {
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0814,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- }
-
- // Return scaled result.
- if (vdigErr == noErr)
- {
- *(pVDigGetSaturationParams->pSaturation) =
- (((fwCCMReg & 0x0FFF) - minValue) << 16) / (maxValue - minValue);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGrabOneFrame
- //
- // This function synchronously grabs one frame of data.
- // This is used when we are watching video on the screen, but can't do
- // playthrough (window size is wrong, color depth is wrong, etc.).
- //
-
- static pascal VideoDigitizerError FWCCMGrabOneFrame(
- Handle componentSpecificData)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCommandObjectID isochChannelCommandObjectID;
- AbsoluteTime currentTime;
- AbsoluteTime timeout;
- Boolean timedOut;
- VideoDigitizerError vdigErr = noErr;
-
- // DebugStrStatus ((ConstStr255Param) "\pFWCCMGrabOneFrame");
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Release asynch buffers if we're in asynch mode.
- if (pFWCCMVDigData->asynchMode)
- FWCCMReleaseAsyncBuffers (componentSpecificData);
-
- // Typically we are doing this over and over, and the DCL program is already
- // running. So, initialize isochronous port only if it isn't initialized.
- if (!(pFWCCMVDigData->channelInitialized))
- {
- // Set up DCL program.
- if (vdigErr == noErr)
- {
- FWCCMSetupDCLProgram (pFWCCMVDigData,
- (DCLCallCommandProcPtr) FWCCMGrabOneFrameIsochHandler);
- vdigErr = FWSetDCLProgramStart (pFWCCMVDigData->dclProgramID,
- pFWCCMVDigData->dclList);
- }
-
- // Initialize isochronous channel.
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- vdigErr = FWInitializeIsochronousChannel (isochChannelCommandObjectID);
- if (vdigErr == noErr)
- pFWCCMVDigData->channelInitialized = true;
-
- // Start isochronous channel.
- if (vdigErr == noErr)
- {
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- pFWCCMVDigData->channelActive = true;
- vdigErr = FWStartIsochronousChannel (isochChannelCommandObjectID);
- }
- }
-
- // Wait until next channel buffer is filled and synced.
- if (vdigErr == noErr)
- {
- // Compute timeout.
- timeout = AddAbsoluteToAbsolute (UpTime (), DurationToAbsolute (durationSecond));
- timedOut = false;
-
- // Wait for a conversion buffer to fill or timeout.
- while ((!((volatile UInt32) pFWCCMVDigData->pendingFrameCount)) &&
- (!timedOut))
- {
- currentTime = UpTime ();
- if (((timeout.lo < currentTime.lo) && (timeout.hi == currentTime.hi)) ||
- (timeout.hi < currentTime.hi))
- {
- timedOut = true;
- }
- }
-
- // Output frame if we didn't timeout.
- if (!timedOut)
- FWCCMCopyToDestPixMap (pFWCCMVDigData);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMPreflightDestination
- //
- // This function verifies that the VDig can support the set of destination
- // settings intended for use with the FWCCMSetPlayThruDestination
- // function.
- //zzz Must do more checks.
- //
-
- static pascal VideoDigitizerError FWCCMPreflightDestination(
- Handle componentSpecificData,
- VDigPreflightDestinationParamsPtr
- pVDigPreflightDestinationParams)
- {
- PixMapHandle hDestPixMap;
- VideoDigitizerError vdigErr = noErr;
-
- /*zzz*/
- DebugStrStatus ((ConstStr255Param) "\pFWCCMPreflightDestination");
- /*zzz*/
- // Check bit depth of pix map.
- hDestPixMap = pVDigPreflightDestinationParams->hDestPixMap;
- if (((*hDestPixMap)->pixelSize != 16) && ((*hDestPixMap)->pixelSize != 32))
- vdigErr = badDepthErr;
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetBlackLevelValue
- //
- // This function sets the black level value for the camera.
- //zzz actually, it sets the U part of the white balance
- //
-
- static pascal VideoDigitizerError FWCCMSetBlackLevelValue(
- Handle componentSpecificData,
- VDigSetBlackLevelValueParamsPtr
- pVDigSetBlackLevelValueParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCCMDriverDataPtr pFWCCMDriverData;
- VDigGetWhiteLevelValueParams
- vdigGetWhiteLevelValueParams;
- FWCommandObjectID asynchCommandObjectID;
- UInt32 fwCCMReg;
- UInt32 minValue,
- maxValue;
- unsigned short *pBlackLevelValue;
- UInt32 blackLevelValue;
- unsigned short whiteLevelValue;
- VideoDigitizerError vdigErr = noErr;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Get the white level value.
- vdigGetWhiteLevelValueParams.pWhiteLevelValue = &whiteLevelValue;
- vdigErr =
- FWCCMGetWhiteLevelValue (componentSpecificData, &vdigGetWhiteLevelValueParams);
-
- // Read the min/max value for the white balance register and scale
- // black level value.
- if (vdigErr == noErr)
- {
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x050C,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- minValue = (fwCCMReg & 0x00FFF000) >> 12;
- maxValue = fwCCMReg & 0x0FFF;
- }
-
- // Scale black and white level values.
- if (vdigErr == noErr)
- {
- pBlackLevelValue = pVDigSetBlackLevelValueParams->pBlackLevelValue;
- blackLevelValue =
- minValue + (((*pBlackLevelValue)*(maxValue - minValue)) >> 16);
- whiteLevelValue =
- minValue + (((whiteLevelValue)*(maxValue - minValue)) >> 16);
- }
-
- // Write the white balance register in the camera.
- if (vdigErr == noErr)
- {
- fwCCMReg = 0x82000000 |
- (blackLevelValue << 12) |
- whiteLevelValue;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x080C,
- (Ptr) &fwCCMReg,
- 4);
-
- FWCCMDelayForHardware (100*durationMillisecond);
- vdigErr = FWWrite (asynchCommandObjectID);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGetBlackLevelValue
- //
- // This function gets the black level for the camera.
- //zzz actually, it gets the U part of the white balance
- //
-
- static pascal VideoDigitizerError FWCCMGetBlackLevelValue(
- Handle componentSpecificData,
- VDigGetBlackLevelValueParamsPtr
- pVdigGetBlackLevelValueParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCommandObjectID asynchCommandObjectID;
- UInt32 fwCCMReg;
- UInt32 minValue,
- maxValue;
- VideoDigitizerError vdigErr = noErr;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Read the min/max value for the hue register.
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x050C,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- minValue = (fwCCMReg & 0x00FFF000) >> 12;
- maxValue = fwCCMReg & 0x0FFF;
-
- // Read the hue register in the camera.
- if (vdigErr == noErr)
- {
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x080C,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- }
-
- // Return scaled result.
- if (vdigErr == noErr)
- {
- *(pVdigGetBlackLevelValueParams->pBlackLevelValue) =
- ((((fwCCMReg & 0x00FFF000) >> 12) - minValue) << 16) /
- (maxValue - minValue);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetWhiteLevelValue
- //
- // This function sets the white level value for the camera.
- //zzz actually, it sets the V part of the white balance
- //
-
- static pascal VideoDigitizerError FWCCMSetWhiteLevelValue(
- Handle componentSpecificData,
- VDigSetWhiteLevelValueParamsPtr
- pVDigSetWhiteLevelValueParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCCMDriverDataPtr pFWCCMDriverData;
- VDigGetBlackLevelValueParams
- vdigGetBlackLevelValueParams;
- FWCommandObjectID asynchCommandObjectID;
- UInt32 fwCCMReg;
- UInt32 minValue,
- maxValue;
- unsigned short *pWhiteLevelValue;
- UInt32 whiteLevelValue;
- unsigned short blackLevelValue;
- VideoDigitizerError vdigErr = noErr;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Get the black level value.
- vdigGetBlackLevelValueParams.pBlackLevelValue = &blackLevelValue;
- vdigErr =
- FWCCMGetBlackLevelValue (componentSpecificData, &vdigGetBlackLevelValueParams);
-
- // Read the min/max value for the white balance register.
- if (vdigErr == noErr)
- {
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x050C,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- minValue = (fwCCMReg & 0x00FFF000) >> 12;
- maxValue = fwCCMReg & 0x0FFF;
- }
-
- // Scale white level value.
- if (vdigErr == noErr)
- {
- pWhiteLevelValue = pVDigSetWhiteLevelValueParams->pWhiteLevelValue;
- blackLevelValue =
- minValue + (((blackLevelValue)*(maxValue - minValue)) >> 16);
- whiteLevelValue =
- minValue + (((*pWhiteLevelValue)*(maxValue - minValue)) >> 16);
- }
-
- // Write the white balance register in the camera.
- if (vdigErr == noErr)
- {
- fwCCMReg = 0x82000000 |
- (blackLevelValue << 12) |
- whiteLevelValue;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x080C,
- (Ptr) &fwCCMReg,
- 4);
-
- FWCCMDelayForHardware (100*durationMillisecond);
- vdigErr = FWWrite (asynchCommandObjectID);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGetWhiteLevelValue
- //
- // This function gets the white level for the camera.
- //zzz actually, it gets the V part of the white balance
- //
-
- static pascal VideoDigitizerError FWCCMGetWhiteLevelValue(
- Handle componentSpecificData,
- VDigGetWhiteLevelValueParamsPtr
- pVDigGetWhiteLevelValueParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCommandObjectID asynchCommandObjectID;
- UInt32 fwCCMReg;
- UInt32 minValue,
- maxValue;
- VideoDigitizerError vdigErr = noErr;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Read the min/max value for the hue register.
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x050C,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- minValue = (fwCCMReg & 0x00FFF000) >> 12;
- maxValue = fwCCMReg & 0x0FFF;
-
- // Read the hue register in the camera.
- if (vdigErr == noErr)
- {
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x080C,
- (Ptr) &fwCCMReg,
- 4);
-
- vdigErr = FWRead (asynchCommandObjectID);
- }
-
- // Return scaled result.
- if (vdigErr == noErr)
- {
- *(pVDigGetWhiteLevelValueParams->pWhiteLevelValue) =
- (((fwCCMReg & 0x0FFF) - minValue) << 16) / (maxValue - minValue);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGetNumberOfInputs
- //
- // This routine returns the number of inputs supported by the VDig.
- //
-
- static pascal VideoDigitizerError FWCCMGetNumberOfInputs(
- Handle componentSpecificData,
- VDigGetNumberOfInputsParamsPtr
- pVDigGetNumberOfInputsParams)
- {
- VideoDigitizerError vdigErr = noErr;
-
- // We only support one input.
- *(pVDigGetNumberOfInputsParams->pNumInputs) = 0;
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGetInput
- //
- // This function returns data that identifies the currently active input
- // video source.
- //
-
- static pascal VideoDigitizerError FWCCMGetInput(
- Handle componentSpecificData,
- VDigGetInputParamsPtr pVDigGetInputParams)
- {
- VideoDigitizerError vdigErr = noErr;
-
- // We only support one input, so it's the one.
- *(pVDigGetInputParams->pInput) = 0;
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetInputStandard
- //
- // This routine returns the number of inputs supported by the VDig.
- //
-
- static pascal VideoDigitizerError FWCCMSetInputStandard(
- Handle componentSpecificData,
- VDigSetInputStandardParamsPtr
- pVDigSetInputStandardParams)
- {
- VideoDigitizerError vdigErr = noErr;
-
- // We only support NTSC.
- //zzz Well we're really just faking it anyway.
- if ((pVDigSetInputStandardParams->inputStandard) != ntscIn)
- vdigErr = qtParamErr;
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetupBuffers
- //
- // This function defines the output buffers to use with asynchronous grabs.
- // This is called before we begin recording video (in Premiere, etc.)
- //zzz need to allocate and copy matrix.
- //zzz This undoes sync grab set up unless called from sync grab set up.
- //
-
- static pascal VideoDigitizerError FWCCMSetupBuffers(
- Handle componentSpecificData,
- VDigSetupBuffersParamsPtr pVDigSetupBuffersParams)
- {
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCCMVDigDataPtr pFWCCMVDigData;
- VdigBufferRecListHandle bufferList;
- FWCommandObjectID asynchCommandObjectID;
- FWCommandObjectID isochChannelCommandObjectID;
- VdigBufferRecListPtr pVdigBufferRecList = nil;
- VdigBufferRec *pVdigBufferRec;
- VdigBufferRecQElemPtr pVdigBufferRecQElemList = nil;
- VdigBufferRecQElemPtr pVdigBufferRecQElem;
- UInt32 numBuffers;
- UInt32 bufferListSize;
- UInt32 fwCCMReg;
- UInt32 i;
- VideoDigitizerError vdigErr = noErr;
-
- // Get buffer list from params.
- bufferList = pVDigSetupBuffersParams->bufferList;
-
- // Release current buffers.
- FWCCMReleaseAsyncBuffers (componentSpecificData);
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Get number of buffers.
- numBuffers = (*bufferList)->count;
-
- // Allocate memory for our copy of buffer list.
- bufferListSize =
- sizeof (VdigBufferRecList) + (numBuffers - 1) * sizeof (VdigBufferRec);
- pVdigBufferRecList =
- (VdigBufferRecListPtr) PoolAllocateResident (bufferListSize, true);
- if (pVdigBufferRecList != nil)
- {
- pVdigBufferRecList->count = (*bufferList)->count;
- }
- else
- {
- vdigErr = memFullErr;
- }
-
- // Allocate memory for and copy pix maps.
- for (i = 0; ((i < numBuffers) && (vdigErr == noErr)); i++)
- {
- pVdigBufferRec = &(pVdigBufferRecList->list[i]);
- pVdigBufferRec->dest = (PixMapHandle) NewHandleClear (sizeof (PixMap));
- if (pVdigBufferRec->dest != nil)
- {
- BlockCopy (*((*bufferList)->list[i].dest),
- *(pVdigBufferRec->dest),
- sizeof (PixMap));
- pVdigBufferRec->location = (*bufferList)->list[i].location;
- }
- else
- {
- vdigErr = memFullErr;
- }
- }
-
- // Allocate memory for queue elements for buffers.
- if (vdigErr == noErr)
- {
- pVdigBufferRecQElemList = (VdigBufferRecQElemPtr)
- PoolAllocateResident (numBuffers * sizeof (VdigBufferRecQElem), true);
- if (pVdigBufferRecQElemList != nil)
- {
- // Fill in queue elements.
- pVdigBufferRecQElem = pVdigBufferRecQElemList;
- pVdigBufferRec = &(pVdigBufferRecList->list[0]);
- for (i = 0; i < numBuffers; i++)
- {
- pVdigBufferRecQElem->pVdigBufferRec = pVdigBufferRec++;
- pVdigBufferRecQElem++;
- }
- }
- else
- {
- vdigErr = memFullErr;
- }
- }
-
- // Set up isochronous channels.
- //zzz should clean this up on error.
- if (vdigErr == noErr)
- {
- // Set up DCL program.
-
- // Reset the jumps and set the callprocs:
- FWCCMSetupDCLProgram (pFWCCMVDigData,
- (DCLCallCommandProcPtr) FWCCMAsyncGrabIsochHandler);
-
- // Set start of DCL program.
- vdigErr = FWSetDCLProgramStart (pFWCCMVDigData->dclProgramID,
- pFWCCMVDigData->dclList);
-
- // Initialize isochronous channel.
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- vdigErr = FWInitializeIsochronousChannel (isochChannelCommandObjectID);
- }
-
- // Channel has now been initialized.
- if (vdigErr == noErr)
- {
- pFWCCMVDigData->channelInitialized = true;
- pFWCCMVDigData->asynchMode = true;
- }
-
- // Set camera to 30 fps.
- if (vdigErr == noErr)
- {
- fwCCMReg = 0x80000000;
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0600,
- (Ptr) &fwCCMReg,
- 4);
-
- FWCCMDelayForHardware (100*durationMillisecond);
- vdigErr = FWWrite (asynchCommandObjectID);
- }
-
- // Start up isochronous channel.
- //zzz do this in FWCCMGrabOneFrameAsync???
- if (vdigErr == noErr)
- {
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- pFWCCMVDigData->channelActive = true;
- vdigErr = FWStartIsochronousChannel (isochChannelCommandObjectID);
- }
-
- // Fill in FWCCM VDig data.
- if (vdigErr == noErr)
- {
- pFWCCMVDigData->pVdigBufferRecList = pVdigBufferRecList;
- pFWCCMVDigData->pVdigBufferRecQElemList = pVdigBufferRecQElemList;
- }
-
- // Clean up on error.
- if (vdigErr != noErr)
- {
- if (pVdigBufferRecList != nil)
- PoolDeallocate ((Ptr) pVdigBufferRecList);
-
- if (pVdigBufferRecQElemList != nil)
- PoolDeallocate ((Ptr) pVdigBufferRecQElemList);
- }
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGrabOneFrameAsync
- //
- // This function starts digitizing asynchronously a single frame of video.
- // I believe this is called for each frame, but since we leave the DCL program
- // running all the time there isn't anything for us to do now.
- //
-
- static pascal VideoDigitizerError FWCCMGrabOneFrameAsync(
- Handle componentSpecificData,
- VDigGrabOneFrameAsyncParamsPtr
- pVDigGrabOneFrameAsyncParams)
- {
- VideoDigitizerError vdigErr = noErr;
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMDone
- //
- // This function returns a non-zero value if the FWCCMGrabOneFrameAsync
- // function is finished with the specified output buffer. Otherwise, this
- // function returns zero.
- //
-
- static pascal long FWCCMDone(
- Handle componentSpecificData,
- VDigDoneParamsPtr pVDigDoneParams)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- VdigBufferRecQElemPtr pVdigBufferRecQElemList;
- VdigBufferRecQElemPtr pVdigBufferRecQElem;
- short buffer;
- UInt32 numBuffers, bufferNum;
- UInt32 i;
-
- // Get buffer from parameters.
- buffer = pVDigDoneParams->buffer;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our list of buffer queue elements.
- pVdigBufferRecQElemList = pFWCCMVDigData->pVdigBufferRecQElemList;
-
- // Queue up all buffers not in use in order starting from buffer.
- numBuffers = pFWCCMVDigData->pVdigBufferRecList->count;
- for (i = 0; i < numBuffers; i++)
- {
- // Get next buffer in line.
- bufferNum = (i + buffer) % numBuffers;
- pVdigBufferRecQElem =
- &(pFWCCMVDigData->pVdigBufferRecQElemList[bufferNum]);
-
- // Add it to queue if it's not in use.
- if (!pVdigBufferRecQElem->inUse)
- {
- // Buffer is now in use and not done.
- pVdigBufferRecQElem->inUse = true;
- pVdigBufferRecQElem->done = false;
-
- // Queue it up.
- PBEnqueueLast ((QElemPtr) pVdigBufferRecQElem,
- pFWCCMVDigData->vdigBufferRecQueue);
- }
- }
-
- // If buffer is done, take it out of use.
- if (pVdigBufferRecQElemList[buffer].done)
- pVdigBufferRecQElemList[buffer].inUse = false;
-
- return (volatile long) pVdigBufferRecQElemList[buffer].done;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMSetFrameRate
- //
- // This function sets the desired frame rate.
- //zzz implement this for real.
- //
-
- static pascal long FWCCMSetFrameRate(
- Handle componentSpecificData,
- VDigSetFrameRateParamsPtr pVDigSetFrameRateParams)
- {
- VideoDigitizerError vdigErr = noErr;
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMReleaseAsyncBuffers
- //
- // This function returns a non-zero value if the FWCCMGrabOneFrameAsync
- // function is finished with the specified output buffer. Otherwise, this
- // function returns zero.
- //
-
- static pascal VideoDigitizerError FWCCMReleaseAsyncBuffers(
- Handle componentSpecificData)
- {
- FWCCMDriverDataPtr pFWCCMDriverData;
- FWCCMVDigDataPtr pFWCCMVDigData;
- FWCommandObjectID asynchCommandObjectID;
- FWCommandObjectID isochChannelCommandObjectID;
- VdigBufferRecListPtr pVdigBufferRecList;
- VdigBufferRecQElemPtr pVdigBufferRecQElemList;
- UInt32 fwCCMReg;
- UInt32 i;
- VideoDigitizerError vdigErr = noErr;
-
- // Get our VDig data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) *componentSpecificData;
-
- // Get our driver data.
- pFWCCMDriverData = pFWCCMVDigData->pFWCCMDriverData;
-
- // Release isochronous channel.
- if (pFWCCMVDigData->channelInitialized)
- {
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- pFWCCMVDigData->channelActive = false;
- FWStopIsochronousChannel (isochChannelCommandObjectID);
-
- isochChannelCommandObjectID = pFWCCMVDigData->isochChannelCommandObjectID;
- FWSetFWCommandParams (isochChannelCommandObjectID,
- kInvalidFWReferenceID,
- kFWCommandSyncFlag,
- nil,
- 0);
- FWSetIsochChannelCommandIsochChannelID (isochChannelCommandObjectID,
- pFWCCMVDigData->isochChannelID);
-
- FWReleaseIsochronousChannel (isochChannelCommandObjectID);
- }
-
- // Channel is no longer initialized.
- pFWCCMVDigData->channelInitialized = false;
- pFWCCMVDigData->asynchMode = false;
-
- // Set camera to 30 fps.
- if (vdigErr == noErr)
- {
- fwCCMReg = 0x80000000;
- asynchCommandObjectID = pFWCCMVDigData->asynchCommandObjectID;
- FWSetCommonAsynchCommandParams (asynchCommandObjectID,
- 0x0000FFFF,
- pFWCCMDriverData->regBaseAddress + 0x0600,
- (Ptr) &fwCCMReg,
- 4);
-
- FWCCMDelayForHardware (100*durationMillisecond);
- vdigErr = FWWrite (asynchCommandObjectID);
- }
-
- // Deallocate buffer rec list.
- pVdigBufferRecList = pFWCCMVDigData->pVdigBufferRecList;
- if (pVdigBufferRecList != nil)
- {
- for (i = 0; i < pVdigBufferRecList->count; i++)
- {
- if (pVdigBufferRecList->list[i].dest != nil)
- DisposeHandle ((Handle) pVdigBufferRecList->list[i].dest);
- }
-
- PoolDeallocate ((Ptr) pVdigBufferRecList);
- pFWCCMVDigData->pVdigBufferRecList = nil;
- }
-
- // Deallocate queue for buffers.
- pVdigBufferRecQElemList = pFWCCMVDigData->pVdigBufferRecQElemList;
- if (pVdigBufferRecQElemList != nil)
- {
- PoolDeallocate ((Ptr) pVdigBufferRecQElemList);
- pFWCCMVDigData->pVdigBufferRecQElemList = nil;
- }
-
- // Initialize vdig buffer queue.
- PBQueueInit (pFWCCMVDigData->vdigBufferRecQueue);
-
- return vdigErr;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMCopyToDestPixMap
- //
- // This routine converts the camera data in the conversion buffer to RGB and
- // copies it into the dest pix map set by FWCCMSetPlayThruDestination.
- // Note however that this is not used with playthrough.
- //
- // Currently hardwired to 4:2:2 30fps
-
- static void FWCCMCopyToDestPixMap(
- FWCCMVDigDataPtr pFWCCMVDigData)
- {
- PixMapHandle hDestPixMap;
- UInt32 *pSrc;
- Ptr pDstRow;
- UInt32 rowBytes;
- UInt32 pixelBytes;
- UInt32 i;
- DCLTransferPacketPtr pDCLCommand;
- UInt32 frameNum;
-
- // Get some vdig parameters.
- hDestPixMap = pFWCCMVDigData->hDestPixMap;
-
- // Convert YUV 4:2:2 to RGB and copy to dest pix map.
- rowBytes = (*hDestPixMap)->rowBytes & 0x7FFF;
- pixelBytes = (*hDestPixMap)->pixelSize >> 3;
-
- // zzz this isn't really right in the pixel-double case, but it works (always 0, 0)
- pDstRow = (*hDestPixMap)->baseAddr +
- pFWCCMVDigData->destRect.top*rowBytes +
- pFWCCMVDigData->destRect.left*pixelBytes;
-
- frameNum = pFWCCMVDigData->pendingFrameNum;
- pDCLCommand = pFWCCMVDigData->firstDCLTransferPacket[frameNum];
-
- for (i = 0; i < 240; i++)
- {
- pSrc = ((UInt32 *) pDCLCommand->buffer) + 1; // skip header
-
- if ((pFWCCMVDigData->destRect.right - pFWCCMVDigData->destRect.left) == 640 &&
- (pFWCCMVDigData->destRect.bottom - pFWCCMVDigData->destRect.top) == 480)
- {
- if ((*hDestPixMap)->pixelSize == 16)
- {
- // zzz what if 411?
- FWCCMConvertYUV422ToRGB16Double (pFWCCMVDigData, pSrc, 640, (UInt32 *) pDstRow, rowBytes);
- }
- else if ((*hDestPixMap)->pixelSize == 32)
- {
- // zzz what if 411?
- FWCCMConvertYUV422ToRGB32Double (pFWCCMVDigData, pSrc, 640, (UInt32 *) pDstRow, rowBytes);
- }
- pDstRow += (rowBytes * 2);
- }
- else // assume 320 x 240
- {
- if ((*hDestPixMap)->pixelSize == 16)
- {
- FWCCMConvertYUV422ToRGB16 (pFWCCMVDigData, pSrc, 640, (UInt32 *) pDstRow, rowBytes);
- }
- else if ((*hDestPixMap)->pixelSize == 32)
- {
- FWCCMConvertYUV422ToRGB32 (pFWCCMVDigData, pSrc, 640, (UInt32 *) pDstRow, rowBytes);
- }
- pDstRow += rowBytes;
- }
-
- // Go to next packet
- pDCLCommand = (DCLTransferPacketPtr) pDCLCommand->pNextDCLCommand;
- }
-
- // Do next frame next time
- pFWCCMVDigData->pendingFrameNum = (frameNum + 1) % kNumFrameBufs;
-
- // One less frame waiting
- DecrementAtomic ((SInt32 *) &(pFWCCMVDigData->pendingFrameCount));
-
- // Now put the frame we used up on the end of the list
- FWCCMSetDCLProgramEndFrame (pFWCCMVDigData, frameNum);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMAsyncGrabIsochHandler
- //
- // This routine handles the isochronous buffers for the async grab calls.
- //
-
- static void FWCCMAsyncGrabIsochHandler(
- DCLCommandPtr pDCLCommandPtr)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- VdigBufferRecQElemPtr pVdigBufferRecQElem;
- DCLCallProcPtr pDCLCallProc;
- DCLTransferPacketPtr pDCLCommand;
- UInt32 packetHeader;
- UInt32 packetSize;
- UInt32 syncBits;
- UInt32 packetNum;
- UInt32 frameNum;
- OSStatus status = noErr;
-
- // Recast DCL command;
- pDCLCallProc = (DCLCallProcPtr) pDCLCommandPtr;
-
- // Get data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) pDCLCallProc->procData;
-
- // Note, probably want to break this up - will need to be more async.
- frameNum = pFWCCMVDigData->pendingFrameNum;
- pDCLCommand = pFWCCMVDigData->firstDCLTransferPacket[frameNum];
-
- // Convert packets and send to destination pix map.
- for (packetNum = 0; packetNum < kNumPacketsPerFrameBuf; packetNum++)
- {
- // Get packet size and sync bits.
- packetHeader = *((UInt32 *) (pDCLCommand->buffer));
- packetSize = (packetHeader & kFWIsochDataLength) >>
- kFWIsochDataLengthPhase;
- syncBits = (packetHeader & kFWIsochSy) >> kFWIsochSyPhase;
-
- // Get vdig buffer at head of queue.
- //zzz maybe we should dequeue it into a vdigdata field before using it.
- if (status == noErr)
- {
- pVdigBufferRecQElem = (VdigBufferRecQElemPtr)
- pFWCCMVDigData->vdigBufferRecQueue->qHead;
- if (pVdigBufferRecQElem == nil)
- {
- // No buffer queued to write into, so skip rest of packets.
- packetNum = kNumPacketsPerFrameBuf;
- status = -1;
- }
- }
-
- // Reset current location if this is the first packet of a frame.
- if ((status == noErr) &&
- ((syncBits == 1) || (pVdigBufferRecQElem->currentLocation.v == 240)))
- {
- pVdigBufferRecQElem->currentLocation.v = 0;
- pVdigBufferRecQElem->currentLocation.h = 0;
- }
-
- // Grab part of the frame.
- if (status == noErr)
- {
- FWCCMCopyIsochChannelToVdigBuffer
- (pFWCCMVDigData, pDCLCommand, pVdigBufferRecQElem);
- }
-
- // Check if we have a complete frame.
- if (status == noErr)
- {
- if (pVdigBufferRecQElem->currentLocation.v == 240)
- {
- // Get next vdig buffer from queue.
- if (status == noErr)
- {
- PBDequeueFirst (pFWCCMVDigData->vdigBufferRecQueue,
- (QElemPtr *) &pVdigBufferRecQElem);
- if (pVdigBufferRecQElem == nil)
- status = -1;
- }
-
- // Buffer is done.
- if (status == noErr)
- {
- pVdigBufferRecQElem->done = true;
- pVdigBufferRecQElem->currentLocation.v = 0;
- pVdigBufferRecQElem->currentLocation.h = 0;
- }
- }
- }
-
- // Update for next packet.
- pDCLCommand = (DCLTransferPacketPtr) pDCLCommand->pNextDCLCommand;
- }
-
- // We finished with the frame - now put it at the end of the DCL program:
-
- // zzz Question: Is it safe to call ModifyJump (done next) if the program
- // was terminated while we did the image processing above?
-
- // We're done with this frame, so make it available at the end of the program.
- FWCCMSetDCLProgramEndFrame (pFWCCMVDigData, frameNum);
-
- // Next time, do the next frame:
- pFWCCMVDigData->pendingFrameNum = (frameNum + 1) % kNumFrameBufs;
-
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMCopyIsochChannelToVdigBuffer
- //
- // This routine converts the camera data in the DCL transfer packet to RGB
- // and copies it into the pix map specified in the VdigBufferRec.
- //zzz assumes channel buffer length is a multiple of 4.
- //
-
- static void FWCCMCopyIsochChannelToVdigBuffer(
- FWCCMVDigDataPtr pFWCCMVDigData,
- DCLTransferPacketPtr pDCLTransferPacket,
- VdigBufferRecQElemPtr pVdigBufferRecQElem)
- {
- VdigBufferRec *pVdigBufferRec;
- PixMapHandle hDestPixMap;
- UInt32 *pSrc;
- Ptr pDstRow;
- UInt32 *pDst;
- UInt32 packetHeader;
- UInt32 rowBytes;
- UInt32 pixelBytes;
- Point baseLocation,
- currentLocation;
- UInt32 bufferSize;
-
- // Get some vdig parameters.
- pVdigBufferRec = pVdigBufferRecQElem->pVdigBufferRec;
- hDestPixMap = pVdigBufferRec->dest;
-
- // Convert YUV 4:2:2 to RGB and copy to dest pix map.
- rowBytes = (*hDestPixMap)->rowBytes & 0x7FFF;
- pixelBytes = (*hDestPixMap)->pixelSize >> 3;
- pSrc = ((UInt32 *) pDCLTransferPacket->buffer) + 1;
- baseLocation = pVdigBufferRec->location;
- currentLocation = pVdigBufferRecQElem->currentLocation;
- packetHeader = *((UInt32 *) (pDCLTransferPacket->buffer));
- bufferSize = (packetHeader & kFWIsochDataLength) >> kFWIsochDataLengthPhase;
-
- if ((pFWCCMVDigData->destRect.right - pFWCCMVDigData->destRect.left) == 640 &&
- (pFWCCMVDigData->destRect.bottom - pFWCCMVDigData->destRect.top) == 480)
- {
- pDstRow = (*hDestPixMap)->baseAddr +
- (baseLocation.v + (currentLocation.v * 2) - (*hDestPixMap)->bounds.top) * rowBytes +
- (baseLocation.h - (*hDestPixMap)->bounds.left) * pixelBytes;
- pDst = (UInt32 *) pDstRow + (currentLocation.h * 2) * pixelBytes;
-
- // zzz what if 411?
- if ((*hDestPixMap)->pixelSize == 16)
- FWCCMConvertYUV422ToRGB16Double (pFWCCMVDigData, pSrc, bufferSize, pDst, rowBytes);
-
- // zzz what if 411?
- if ((*hDestPixMap)->pixelSize == 32)
- FWCCMConvertYUV422ToRGB32Double (pFWCCMVDigData, pSrc, bufferSize, pDst, rowBytes);
- }
- else // 320 x 240
- {
- pDstRow = (*hDestPixMap)->baseAddr +
- (baseLocation.v + currentLocation.v - (*hDestPixMap)->bounds.top) * rowBytes +
- (baseLocation.h - (*hDestPixMap)->bounds.left) * pixelBytes;
- pDst = (UInt32 *) pDstRow + currentLocation.h * pixelBytes;
-
- if ((*hDestPixMap)->pixelSize == 16)
- FWCCMConvertYUV422ToRGB16 (pFWCCMVDigData, pSrc, bufferSize, pDst, rowBytes);
-
- if ((*hDestPixMap)->pixelSize == 32)
- FWCCMConvertYUV422ToRGB32 (pFWCCMVDigData, pSrc, bufferSize, pDst, rowBytes);
- }
-
- pVdigBufferRecQElem->currentLocation.v++;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMPlayThruIsochHandler
- //
- // This routine handles the isochronous buffers for play thru.
- //
-
- static void FWCCMPlayThruIsochHandler(
- DCLCommandPtr pDCLCommandPtr)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- DCLCallProcPtr pDCLCallProc;
- DCLTransferPacketPtr pDCLCommand;
- UInt32 packetHeader;
- UInt32 syncBits;
- UInt32 packetNum;
- UInt32 frameNum;
- AbsoluteTime startTime, endTime, runTime;
- Duration duration;
- OSStatus status = noErr;
-
- // DebugStrStatus ((ConstStr255Param) "\pFWCCMPlayThruIsochHandler");
-
- startTime = UpTime ();
-
- // Recast DCL command;
- pDCLCallProc = (DCLCallProcPtr) pDCLCommandPtr;
-
- // Get data
- pFWCCMVDigData = (FWCCMVDigDataPtr) pDCLCallProc->procData;
-
- // Ultimately, we want to do the conversion in chunks.
- // When we do, make sure we can't queue some work, and stop and restart the
- // program before the work gets done. That would be a mess.
- // For now, do it all at once:
- frameNum = pFWCCMVDigData->pendingFrameNum; // not correct if we're async
- pDCLCommand = pFWCCMVDigData->firstDCLTransferPacket[frameNum];
-
- if (pFWCCMVDigData->skipFrameCounter)
- {
- pFWCCMVDigData->skipFrameCounter--;
- }
- else
- {
- // Convert packets and send to destination pix map.
- for (packetNum = 0; packetNum < kNumPacketsPerFrameBuf; packetNum++)
- {
- // Get sync bits.
- packetHeader = *((UInt32 *) (pDCLCommand->buffer));
- syncBits = (packetHeader & kFWIsochSy) >> kFWIsochSyPhase;
-
- // Set to top of frame if sync bits indicate this packet as the
- // top of frame (Lynx), or if we've filled up a frame (Lynx/Pele).
- if ((syncBits == 1) || (pFWCCMVDigData->currentLocation.v == 240))
- {
- pFWCCMVDigData->currentLocation.v = 0;
- pFWCCMVDigData->currentLocation.h = 0;
- }
-
- // Transfer packet data to destination pix map.
- FWCCMCopyIsochChannelToDestPixMap (pFWCCMVDigData, pDCLCommand);
-
- // Go to next packet.
- pDCLCommand = (DCLTransferPacketPtr) pDCLCommand->pNextDCLCommand;
- }
- }
- // zzz Question: Is it safe to call ModifyJump (done next) if the program
- // was terminated while we did the image processing above?
-
- // We're done with this frame, so make it available at the end of the program.
- FWCCMSetDCLProgramEndFrame (pFWCCMVDigData, frameNum);
-
- // Check how long the conversion took. Note that the documentation in
- // Designing PCI Cards and Drivers seems to be backwards, regarding subtraction
- endTime = UpTime ();
- runTime = SubAbsoluteFromAbsolute (endTime, startTime);
- duration = AbsoluteToDuration (runTime);
-
- // Duration could be milliseconds (positive) or microseconds (negative)
- if (duration < 0)
- duration = duration / -1000;
-
- // 1/30 of a second is 33 milliseconds. If we spend more than 30 milliseconds
- // doing this conversion, we might be falling behind. Conversely, if we spend
- // less than 25, assume that all is well. (Times consistently under 31 will
- // cause no skipping, but a time under 25 will undo any over-30 we recently saw.)
-
- if (duration > (durationMillisecond * 30))
- pFWCCMVDigData->slowFrameCounter++;
-
- if (duration < (durationMillisecond * 25))
- pFWCCMVDigData->slowFrameCounter = 0;
-
- // If we have more than 4 slow frames before a fast one, we are probably
- // saturated (or very close). To recover, skip the next two frames. This
- // makes the image stream bursty, but if we skip only one, the DMA may have
- // another frame already waiting for us, and we will not recover.
-
- if (pFWCCMVDigData->slowFrameCounter > 4)
- {
- pFWCCMVDigData->slowFrameCounter = 0;
- pFWCCMVDigData->skipFrameCounter = 2;
- }
-
- // Next time, do the next frame:
- pFWCCMVDigData->pendingFrameNum = (frameNum + 1) % kNumFrameBufs;
-
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMGrabOneFrameIsochHandler
- //
- // This routine handles the isochronous buffers for grab one frame.
- // Generally this is used when we watch video without using playthrough.
- //
-
- static void FWCCMGrabOneFrameIsochHandler(
- DCLCommandPtr pDCLCommandPtr)
- {
- FWCCMVDigDataPtr pFWCCMVDigData;
- DCLCallProcPtr pDCLCallProc;
- OSStatus status = noErr;
-
- // DebugStrStatus ((ConstStr255Param) "\pFWCCMGrabOneFrameIsochHandler");
-
- // Recast DCL command;
- pDCLCallProc = (DCLCallProcPtr) pDCLCommandPtr;
-
- // Get data.
- pFWCCMVDigData = (FWCCMVDigDataPtr) pDCLCallProc->procData;
-
- // Instead of copying the data, just leave it in place.
- IncrementAtomic ((SInt32 *) &(pFWCCMVDigData->pendingFrameCount));
-
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMCopyIsochChannelToDestPixMap
- //
- // This routine converts the camera data in the DCL transfer packet to RGB
- // and copies it into the dest pix map by FWCCMSetPlayThruDestination.
-
- static void FWCCMCopyIsochChannelToDestPixMap(
- FWCCMVDigDataPtr pFWCCMVDigData,
- DCLTransferPacketPtr pDCLTransferPacket)
- {
- PixMapHandle hDestPixMap;
- Ptr pDstRow;
- UInt32 *pSrc, *pDst;
- UInt32 packetHeader;
- UInt32 rowBytes, pixelBytes;
- Point baseLocation, currentLocation;
- SInt32 bufferSize;
-
- // Get some vdig parameters.
- hDestPixMap = pFWCCMVDigData->hDestPixMap;
-
- // Convert YUV 4:2:2 to RGB and copy to dest pix map.
- rowBytes = (*hDestPixMap)->rowBytes & 0x7FFF;
- pixelBytes = (*hDestPixMap)->pixelSize >> 3;
- pSrc = (UInt32 *) (pDCLTransferPacket->buffer + sizeof (UInt32));
- packetHeader = *((UInt32 *) (pDCLTransferPacket->buffer));
- bufferSize = (packetHeader & kFWIsochDataLength) >> kFWIsochDataLengthPhase;
- baseLocation.h = pFWCCMVDigData->destRect.left;
- baseLocation.v = pFWCCMVDigData->destRect.top;
- currentLocation = pFWCCMVDigData->currentLocation;
-
- if ((pFWCCMVDigData->destRect.right - pFWCCMVDigData->destRect.left) == 640 &&
- (pFWCCMVDigData->destRect.bottom - pFWCCMVDigData->destRect.top) == 480)
- {
- pDstRow = (*hDestPixMap)->baseAddr +
- (baseLocation.v + currentLocation.v * 2) * rowBytes +
- baseLocation.h * pixelBytes;
- pDst = (UInt32 *) (pDstRow + currentLocation.h * pixelBytes * 2);
-
- // zzz what if 411?
- if ((*hDestPixMap)->pixelSize == 16)
- FWCCMConvertYUV422ToRGB16Double (pFWCCMVDigData, pSrc, (UInt32) bufferSize, pDst, rowBytes);
-
- // zzz what if 411?
- if ((*hDestPixMap)->pixelSize == 32)
- FWCCMConvertYUV422ToRGB32Double (pFWCCMVDigData, pSrc, (UInt32) bufferSize, pDst, rowBytes);
- }
- else // assume 320 x 240
- {
- pDstRow = (*hDestPixMap)->baseAddr +
- (baseLocation.v + currentLocation.v) * rowBytes +
- baseLocation.h * pixelBytes;
- pDst = (UInt32 *) (pDstRow + currentLocation.h * pixelBytes);
-
- if ((*hDestPixMap)->pixelSize == 16)
- FWCCMConvertYUV422ToRGB16 (pFWCCMVDigData, pSrc, (UInt32) bufferSize, pDst, rowBytes);
-
- if ((*hDestPixMap)->pixelSize == 32)
- FWCCMConvertYUV422ToRGB32 (pFWCCMVDigData, pSrc, (UInt32) bufferSize, pDst, rowBytes);
- }
-
- pFWCCMVDigData->currentLocation.v++;
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMConvertYUV422ToRGB16
- //
- // This routine converts YUV 4:2:2 data into 16-bit RGB data, presumably in a
- // pixMap or similar structure. Only whole scanlines are supported (multiple
- // scanlines will work). We use aligned 32-bit writes to the target, as long
- // as the target is at least 16-bit aligned.
- //
- // This routine is rather optimized, and that makes it hard to read. See the
- // comments in FWCCMConvertYUV422ToRGB32 that apply to the 320x240 case for
- // some explanation.
-
- static void FWCCMConvertYUV422ToRGB16(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 *pSrcYUV, // YUV 4:2:2 Source pointer
- UInt32 byteCountYUV, // Source length in bytes
- UInt32 *pDstRGB, // RGB 16 Destination pointer
- UInt32 rowBytesRGB) // Byte offset to next row of destination
- {
- UInt32 *pSrc, *pDstRow, *pDst1, *pDst2;
- UInt32 bufferSize, loops;
- UInt32 srcYUV, Y1, U, V, Y2, UV;
- UInt16 hold;
- Ptr table;
-
- pSrc = pSrcYUV;
- pDstRow = pDstRGB;
- bufferSize = byteCountYUV;
- table = (Ptr) pFWCCMVDigData->yuvToRGB16Table;
-
- while (bufferSize > 0)
- {
- pDst1 = pDstRow;
- loops = 160; // 2 pixels per loop, 320 pixels total
- bufferSize -= 640; // consume 640 bytes of source YUV
-
- if (bufferSize)
- pDstRow = (UInt32 *) (((UInt32) pDstRow) + rowBytesRGB);
-
- // Warning - compiler (PPCC) is very sensitive about pDst1. Masking it & 0x03
- // causes one of the two loops to be optimized into nothingness. Sigh.
-
- // Might be faster to support double-aligned float writes
-
- pDst2 = (UInt32 *) (((UInt32) pDst1) & 0xFFFFFFFC);
- if (pDst2 == pDst1) // pDst1 is quad-aligned, use simple loop
- {
- while (loops--)
- {
- srcYUV = *pSrc++;
- U = (srcYUV & 0xF8000000) >> 21;
- V = (srcYUV & 0xF800) >> 10;
- Y1 = (srcYUV & 0xFC0000) >> 7;
- UV = U | V;
- Y2 = (srcYUV & 0xFC) << 9;
-
- // Could eliminate the << 16 by using a precomputed (table - 1) (+1?)
-
- *pDst1++ = ((*((UInt16 *) (table + (Y1 | UV)))) << 16) | // one pixel
- *((UInt16 *) (table + (Y2 | UV))); // another
- }
- }
- else // pDst1 is not quad-aligned (must be half-quad aligned)
- {
- srcYUV = *pSrc++;
- U = (srcYUV & 0xF8000000) >> 21;
- V = (srcYUV & 0xF800) >> 10;
- Y1 = (srcYUV & 0xFC0000) >> 7;
- UV = U | V;
- Y2 = (srcYUV & 0xFC) << 9;
-
- *((UInt16 *) pDst1) = *((UInt16 *) (table + (Y1 | UV))); // first pixel
- hold = *((UInt16 *) (table + (Y2 | UV))); // next
- pDst1 = (UInt32 *) (((UInt32) pDst1) + 2);
- loops--;
-
- while (loops--)
- {
- srcYUV = *pSrc++;
- U = (srcYUV & 0xF8000000) >> 21;
- V = (srcYUV & 0xF800) >> 10;
- Y1 = (srcYUV & 0xFC0000) >> 7;
- UV = U | V;
- Y2 = (srcYUV & 0xFC) << 9;
- *pDst1++ = (hold << 16) | *((UInt16 *) (table + (Y1 | UV)));
- hold = *((UInt16 *) (table + (Y2 | UV)));
- }
-
- *((UInt16 *) pDst1)++ = hold; // final pixel
- }
- }
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMConvertYUV422ToRGB16Double
- //
- // This routine converts YUV 4:2:2 data to pixel-doubled 16-bit RGB data, in a
- // pixMap or similar structure. Only whole scanlines are supported (multiple
- // scanlines will work). If the destination is 32-bit aligned, we will use
- // 64-bit writes for speed (ideally the destination is 64-bit aligned).
- // Otherwise we use 32-bit writes and performance is not quite as good.
- //
- // This routine is rather optimized, and that makes it hard to read. See the
- // comments in FWCCMConvertYUV422ToRGB32 that apply to the 320x240 case for
- // some explanation.
-
- static void FWCCMConvertYUV422ToRGB16Double(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 *pSrcYUV, // YUV 4:2:2 Source pointer
- UInt32 byteCountYUV, // Source length in bytes
- UInt32 *pDstRGB, // RGB 16 Destination pointer
- UInt32 rowBytesRGB) // Byte offset to next row of destination
- {
- UInt32 *pSrc, *pDstRow, *pDst1, *pDst2;
- UInt32 bufferSize, loops;
- UInt32 srcYUV, Y1, U, V, Y2, UV;
- UInt16 hold, pix1, pix2;
- Ptr table;
- double dub;
-
- pSrc = pSrcYUV;
- pDstRow = pDstRGB;
- bufferSize = byteCountYUV;
- table = (Ptr) pFWCCMVDigData->yuvToRGB16Table;
-
- while (bufferSize > 0)
- {
- pDst1 = pDstRow;
- loops = 160;
- bufferSize -= 640;
-
- if (bufferSize)
- pDstRow = (UInt32 *) (((UInt32) pDstRow) + rowBytesRGB); // not likely!
-
- // Warning - compiler (PPCC) is very sensitive about pDst1. Masking it & 0x03
- // causes one of the two loops to be optimized into nothingness. Sigh.
-
- pDst2 = (UInt32 *) (((UInt32) pDst1) & 0xFFFFFFFC);
- if (pDst2 == pDst1) // pDst1 is quad-aligned, use simple loop
- {
- pDst2 = (UInt32 *) (((UInt32) pDst1) + rowBytesRGB);
- while (loops--)
- {
- srcYUV = *pSrc++;
- U = (srcYUV & 0xF8000000) >> 21;
- V = (srcYUV & 0xF800) >> 10;
- Y1 = (srcYUV & 0xFC0000) >> 7;
- UV = U | V;
- Y2 = (srcYUV & 0xFC) << 9;
- pix1 = *((UInt16 *) (table + (Y1 | UV)));
- pix2 = *((UInt16 *) (table + (Y2 | UV)));
-
- // double-writes helps, but there's room for improvement still:
-
- *((UInt32 *) &dub) = pix1 | (pix1 << 16);
- *((UInt32 *) (((Ptr) (&dub)) + 4)) = pix2 | (pix2 << 16);
- *((double *) (pDst1)) = dub;
- *((double *) (pDst2)) = dub;
- pDst1 += 2;
- pDst2 += 2;
- }
- }
- else // pDst1 is not quad-aligned (must be half-quad aligned)
- {
- pDst2 = (UInt32 *) (((UInt32) pDst1) + rowBytesRGB);
- srcYUV = *pSrc++;
- U = (srcYUV & 0xF8000000) >> 21;
- V = (srcYUV & 0xF800) >> 10;
- Y1 = (srcYUV & 0xFC0000) >> 7;
- UV = U | V;
- Y2 = (srcYUV & 0xFC) << 9;
-
- // could be faster (two unaligned writes)
- hold = *((UInt16 *) (table + (Y1 | UV))); // first
- *pDst1++ = hold | (hold << 16);
- *pDst2++ = hold | (hold << 16);
- hold = *((UInt16 *) (table + (Y2 | UV))); // next
- *((UInt16 *) pDst1) = hold;
- *((UInt16 *) pDst2) = hold;
- pDst1 = (UInt32 *) (((UInt32) pDst1) + 2);
- pDst2 = (UInt32 *) (((UInt32) pDst2) + 2);
- loops--;
-
- while (loops--)
- {
- srcYUV = *pSrc++;
- U = (srcYUV & 0xF8000000) >> 21;
- V = (srcYUV & 0xF800) >> 10;
- Y1 = (srcYUV & 0xFC0000) >> 7;
- UV = U | V;
- Y2 = (srcYUV & 0xFC) << 9;
-
- pix1 = *((UInt16 *) (table + (Y1 | UV)));
- pix2 = *((UInt16 *) (table + (Y2 | UV)));
- *pDst1++ = pix1 | (hold << 16);
- *pDst2++ = pix1 | (hold << 16);
- *pDst1++ = pix2 | (pix1 << 16);
- *pDst2++ = pix2 | (pix1 << 16);
-
- hold = pix2;
- }
-
- *((UInt16 *) pDst1) = hold; // final pixel
- *((UInt16 *) pDst2) = hold; // final pixel
- }
- }
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMConvertYUV422ToRGB32
- //
- // This routine converts YUV 4:2:2 data into 32-bit RGB data, presumably in a
- // pixMap or similar structure. Only whole scanlines are supported (multiple
- // scanlines will work). We use 32-bit writes, and assume that the target will
- // be 32-bit aligned (since it is 32 bits per pixel).
- //
- // This routine has slightly more comments than the others.
-
- static void FWCCMConvertYUV422ToRGB32(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 *pSrcYUV, // YUV 4:2:2 Source pointer
- UInt32 byteCountYUV, // Source length in bytes
- UInt32 *pDstRGB, // RGB 16 Destination pointer
- UInt32 rowBytesRGB) // Byte offset to next row of destination
- {
- UInt32 *pSrc, *pDstRow, *pDst1, *pDst2;
- UInt32 bufferSize, loops;
- UInt32 srcYUV, Y1, U, V, Y2, UV;
- Ptr table;
-
- pSrc = pSrcYUV;
- pDstRow = pDstRGB;
- bufferSize = byteCountYUV;
- table = (Ptr) pFWCCMVDigData->yuvToRGB32Table;
-
- while (bufferSize > 0)
- {
- pDst1 = pDstRow;
- pDst2 = pDst1 + 1; // for pipelining
- loops = 160; // 2 pixels per loop, 320 pixels total
- bufferSize -= 640; // consume 640 bytes of source YUV
-
- if (bufferSize)
- pDstRow = (UInt32 *) (((UInt32) pDstRow) + rowBytesRGB);
-
- // Might be faster to support double-aligned float writes
-
- while (loops--)
- {
- // The following statements make more sense, and do the same thing,
- // but require ~60% more instructions. (UInt8 Y, U, V, *pSrc)
- //
- // U = pSrc[0] & 0xF8; // 5 bits
- // Y = pSrc[1] & 0xFC; // 6 bits
- // V = pSrc[2] & 0xF8; // 5 bits
- // *pDst++ = yuvToRGBTable[(Y << 8) | (U << 2) | (V >> 3)];
- // Y = pSrc[3] & 0xFC;
- // *pDst++ = yuvToRGBTable[(Y << 8) | (U << 2) | (V >> 3)];
-
- srcYUV = *pSrc++;
- U = (srcYUV & 0xF8000000) >> 20;
- V = (srcYUV & 0xF800) >> 9;
- Y1 = (srcYUV & 0xFC0000) >> 6;
- UV = U | V;
- Y2 = (srcYUV & 0xFC) << 10;
- *pDst1 = *((UInt32 *) (table + (Y1 | UV)));
- pDst1 += 2;
- *pDst2 = *((UInt32 *) (table + (Y2 | UV)));
- pDst2 += 2;
- }
- }
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMConvertYUV422ToRGB32Double
- //
- // This routine converts YUV 4:2:2 data to pixel-doubled 32-bit RGB data, in a
- // pixMap or similar structure. Only whole scanlines are supported (multiple
- // scanlines will work).
- //
- // This routine is rather optimized, and that makes it hard to read. See the
- // comments in FWCCMConvertYUV422ToRGB32 that apply to the 320x240 case for
- // some explanation. We use 64-bit aligned writes regardless of target alignment.
- // Performance is best with 64-bit aligned targets.
-
- static void FWCCMConvertYUV422ToRGB32Double(
- FWCCMVDigDataPtr pFWCCMVDigData,
- UInt32 *pSrcYUV, // YUV 4:2:2 Source pointer
- UInt32 byteCountYUV, // Source length in bytes
- UInt32 *pDstRGB, // RGB 16 Destination pointer
- UInt32 rowBytesRGB) // Byte offset to next row of destination
- {
- UInt32 *pSrc, *pDstRow, *pDst1, *pDst2;
- UInt32 bufferSize, loops;
- UInt32 srcYUV, Y1, U, V, Y2, UV;
- Ptr table;
- double dub;
-
- pSrc = pSrcYUV;
- pDstRow = pDstRGB;
- bufferSize = byteCountYUV;
- table = (Ptr) pFWCCMVDigData->yuvToRGB32Table;
-
- while (bufferSize > 0)
- {
- pDst1 = pDstRow;
- pDst2 = (UInt32 *) (((UInt32) pDst1) + rowBytesRGB);
- loops = 160;
- bufferSize -= 640;
-
- if (bufferSize)
- pDstRow = (UInt32 *) (((UInt32) pDstRow) + rowBytesRGB); // not likely!
-
- while (loops--)
- {
- srcYUV = *pSrc++;
- U = (srcYUV & 0xF8000000) >> 20;
- V = (srcYUV & 0xF800) >> 9;
- Y1 = (srcYUV & 0xFC0000) >> 6;
- UV = U | V;
- Y2 = (srcYUV & 0xFC) << 10;
-
- // double writes are a big help ... when the pixmap is double aligned.
- // they help much less when not aligned. Fix this loop to handle both.
-
- *((UInt32 *) &dub) = *((UInt32 *) (table + (Y1 | UV)));
- *((UInt32 *) (((Ptr) (&dub)) + 4)) = *((UInt32 *) (table + (Y1 | UV)));
- *((double *) (pDst1)) = dub;
- *((double *) (pDst2)) = dub;
- pDst1 += 2;
- pDst2 += 2;
-
- *((UInt32 *) &dub) = *((UInt32 *) (table + (Y2 | UV)));
- *((UInt32 *) (((Ptr) (&dub)) + 4)) = *((UInt32 *) (table + (Y2 | UV)));
- *((double *) (pDst1)) = dub;
- *((double *) (pDst2)) = dub;
- pDst1 += 2;
- pDst2 += 2;
- }
- }
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMDelayForHardware
- //
- // Delay for the amount of time given in duration units.
- //
-
- static void FWCCMDelayForHardware(
- Duration duration)
- {
- AbsoluteTime absoluteDuration;
-
- absoluteDuration = DurationToAbsolute (duration);
- DelayForHardware (absoluteDuration);
- }
-
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- // FWCCMClientCommandCompletionProc
- //
- // This routine does generic completion of FireWire client commands that
- // make asynchronous FireWire service calls.
- //
-
- static void FWCCMClientCommandCompletionProc(
- FWCommandObjectID fwCommandObjectID,
- OSStatus commandStatus,
- UInt32 completionProcData)
- {
- FWClientCommandIsComplete ((FWClientCommandID) completionProcData, commandStatus);
- }
-